繁体   English   中英

从GUID获取类型

[英]Get type from GUID

由于各种原因,我需要在C#中实现类型缓存机制。 幸运的是,CLR提供Type.GUID来唯一标识一个类型。 不幸的是,我找不到任何方法来查找基于此GUID的类型。 Type.GetTypeFromCLSID()但基于我对文档(和实验)的理解,它们做了非常非常不同的事情。

是否有任何方法可以获得基于其GUID的类型,而不是循环遍历所有已加载的类型并与其GUID进行比较?

编辑 :我忘了提到我真的很喜欢固定宽度的“类型指纹”,这就是为什么GUID对我这么有吸引力。 当然,在一般情况下,该类型的完全限定名称可以使用。

为什么不使用指定的财产,即。 AssemblyQualifiedName 此属性记录为“可以持久化并稍后用于加载类型”。

GUID用于COM互操作。

这可能只是已经发布的答案的摘要,但我认为没有首先构建Guid-> Type的地图就有办法做到这一点。

我们在初始化框架中执行此操作:

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方法可能是可取的。

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

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

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

这肯定会给你一个固定大小的条目,因为它们都是对象引用(Type的实例基本上是工厂对象)。

那么(来自Generating Deterministic GUID ):

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 (警告:可能发生冲突)。

如果您掌控这些课程我会建议:

public interface ICachable
{
    Guid ClassId { get; }
}

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

您可以使用Visual Studio,Tools-> Create Guid生成GUID。

Mono文档报告模块具有guane元数据堆

也许Cecil可能会帮助您根据其guid查找类型? 不过不确定,有一个GuidHeap类,它似乎正在生成guid,但也许这足以让你的缓存工作?

我会使用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>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM