.net 从GUID获取类型

zqry0prt  于 2023-03-09  发布在  .NET
关注(0)|答案(7)|浏览(149)

由于各种原因,我需要在C#中实现类型缓存机制。幸运的是,CLR提供了Type.GUID来唯一标识类型。不幸的是,我找不到任何基于此GUID查找类型的方法。有Type.GetTypeFromCLSID(),但基于我对文档(和实验)的理解,它做的事情非常非常不同。
除了循环遍历所有加载的类型并与它们的GUID进行比较之外,是否有任何方法可以基于类型的GUID来获取类型?

EDIT:我忘了说我真的想要一个固定宽度的“type fingerprint”,这就是为什么GUID对我如此有吸引力。当然,在一般情况下,类型的完全限定名将起作用。

ecr0jaav

ecr0jaav1#

为什么不为此使用指定的属性,即AssemblyQualifiedName?此属性被记录为“可以持久化,稍后用于加载类型”。
GUID用于COM互操作。

0kjbasz6

0kjbasz62#

这可能只是对已经发布的答案的总结,但我认为如果不首先构建一个Guid-〉Type的Map,就没有办法做到这一点。
我们在初始化的框架中这样做:

static TypeManager()
    {
        AppDomain.CurrentDomain.AssemblyLoad += (s, e) =>
        {
            _ScanAssembly(e.LoadedAssembly);
        };

        foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
        {
            _ScanAssembly(a);
        }
    }

    private static void _ScanAssembly(Assembly a)
    {
        foreach (Type t in a.GetTypes())
        {
           //optional check to filter types (by interface or attribute, etc.)
           //Add type to type map   
        }
    }

处理AssemblyLoad事件会处理动态加载的程序集。
据我所知,Type.GUID使用类型的程序集版本作为GUID生成算法的一部分。如果您增加程序集版本号,这可能会导致问题。根据您的应用程序,使用另一个答案中描述的GetDeterministicGuid方法可能是可取的。

6psbrbz9

6psbrbz93#

不要循环比较。填充Dictionary<Type>并使用Contains方法。

Dictionary<Type> types = new Dictionary<Types>();
... //populate 

if (types.Contains(someObject.GetType())) 
  //do something

这肯定会给予你一个固定大小的条目,因为所有的条目都是对象引用(Type的示例本质上是工厂对象)。

xmakbtuz

xmakbtuz4#

关于(来自Generating Deterministic GUIDs):

private Guid GetDeterministicGuid(string input)
{
    // use MD5 hash to get a 16-byte hash of the string:
    MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
    byte[] inputBytes = Encoding.Default.GetBytes(input);
    byte[] hashBytes = provider.ComputeHash(inputBytes);
    
    // generate a guid from the hash:
    Guid hashGuid = new Guid(hashBytes);
    return hashGuid;
}

再加上typeof().AssemblyQualifiedName,你可以把这些数据存储在一个Dictionary<string, Guid>集合中(或者,随便什么,<Guid, string>)。
这样,对于给定的类型,您将始终拥有相同的GUID(警告:冲突是可能的)。

ymdaylpp

ymdaylpp5#

如果你能控制这些课程,我建议你:

public interface ICachable
{
    Guid ClassId { get; }
}

public class Person : ICachable
{
    public Guid ClassId
    {
        get {  return new Guid("DF9DD4A9-1396-4ddb-98D4-F8F143692C45"); }
    }
}

您可以使用Visual Studio、工具-〉创建GUID来生成GUID。

b09cbbtk

b09cbbtk6#

Mono文档报告说模块有一个guid的元数据堆。
也许Cecil可以帮助你根据guid查找一个类型?虽然不确定,有一个GuidHeap类,它似乎正在生成guid,但也许这足以让你的缓存工作?

b1uwtaje

b1uwtaje7#

我将使用typeof(class).GUID该高速缓存字典中查找示例:

private Dictionary<Guid, class> cacheDictionary { get; set; }

我会有一个返回字典的方法,并将GUID作为在字典中搜索类的方法的参数。

public T Getclass<T>()
    {
        var key = typeof(T).GUID;
        var foundClass= cacheDictionary.FirstOrDefault(x => x.Key == key);
        T item;
        if (foundClass.Equals(default(KeyValuePair<Guid, T>)))
        {
            item = new T()
            cacheDictionary.Add(key, item);
        }
        else
            item = result.Value;

        return item;
    }

我会该高速缓存使用单例模式,
这个调用将类似于下面的代码:

var cachedObject = Cache.Instance.Getclass<class>();

相关问题