由于各种原因,我需要在C#中实现类型缓存机制。幸运的是,CLR提供Type.GUID
来唯一标识类型。不幸的是,我找不到任何方法来查找基于此GUID的类型。有Type.GetTypeFromCLSID()
但基于我对文档(和实验)的理解,它们做了非常非常不同的事情。
有没有办法根据GUID获取一个类型,而不是循环遍历所有加载的类型并与它们的GUID进行比较?
编辑:我忘了提到我真的很喜欢固定宽度的“类型指纹”,这就是为什么GUID对我这么有吸引力的原因。当然,在一般情况下,该类型的完全限定名称可以使用。
答案 0 :(得分:7)
为什么不使用指定的属性,即。 AssemblyQualifiedName?此属性记录为“可以保留并稍后用于加载类型”。
GUID适用于COM互操作。
答案 1 :(得分:4)
这可能只是已经发布的答案的摘要,但我认为没有办法在没有首先构建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方法可能是可取的。
答案 2 :(得分:3)
不要循环比较。填充Dictionary<Type>
并使用Contains
方法。
Dictionary<Type> types = new Dictionary<Types>();
... //populate
if (types.Contains(someObject.GetType()))
//do something
这肯定会给你一个固定大小的条目,因为它们都是对象引用(Type的实例基本上是工厂对象)。
答案 3 :(得分:1)
(来自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
(警告:可能发生碰撞)。
答案 4 :(得分:0)
如果您掌控这些课程,我建议:
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。
答案 5 :(得分:0)
Mono文档报告模块具有Metadata heap of guids。
也许Cecil可能会帮助您根据其guid查找类型?虽然不确定,有一个GuidHeap类,但它似乎正在生成guid,但是这可能足以让你的缓存工作了吗?
答案 6 :(得分:0)
我会使用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>();