如果我这样做,我枚举程序中的所有类型:
List<SerializableAttribute> attributes=new List<SerializableAttribute>() ;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
attributes.AddRange(
type.GetCustomAttributes(false)
.OfType<SerializableAttribute>()
.ToList());
}
}
是与。net dll索引的元数据,允许我做以下事情:
List<SerializableAttribute> attributes = typeof(SerializableAttribute)
.GetClassesIAmDefinedOn();
还有其他我没有考虑的选择吗?
(SerializableAttribute只是一个例子)
好吧,更多地使用LINQ和使用IsDefined
至少使代码更好(并获取类型,而不是属性…)
var types = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where Attribute.IsDefined(type, typeof(SerializableAttribute))
select type).ToList();
现在,你问效率——这需要多长时间?可以接受需要多长时间?你经常打这个电话吗?(这看起来很奇怪。)
还要注意,它只包括已经加载的程序集-可能有一个尚未加载的引用程序集;没人接电话有关系吗?
最有效的东西在这里使用一般是Attribute.IsDefined(...)
,虽然在[Serializable]
的特定情况下,type.IsSerializable
更快(它实际上不是作为一个属性存储在这种情况下-它在编译器中有特殊的处理,映射到CLI标志)。
不,不是。注意GetCustomAttributes。它非常昂贵,而且不能有效地缓存。AppDomain.Current.Domain.GetAssemblies也非常昂贵。
为了做到这一点,我在Dictionary
中保留了一个缓存var cache = new Dictionary<Assembly,Attribute[]>();
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var attributes = new List<SerializableAttribute>();
foreach (Type type in assembly.GetTypes())
{
attributes.AddRange(
type.GetCustomAttributes(false)
.OfType<SerializableAttribute>()
.ToList());
}
cache[assembly] = attributes.ToArray();
}
你可以这样做:
var assem = // get assembly:
var types = assem.GetTypes().Where(t => t.IsDefined(typeof(SerializableAttribute)));
或者,如果你想反过来做:
public static IEnumerable<Type> WhereDefinedOn(this Type type, IEnumerable<Type> types)
{
if (!typeof(Attribute).IsAssignableFrom(type))
throw new InvalidOperationException("Only attribute types are supported.");
return types.Where(t => t.IsDefined(type));
}
可以用
var allTypes = assem.GetTypes();
var filteredTypes = typeof(SerializableAttribute).WhereDefinedOn(allTypes);