最有效的方法来获得所有类型在AppDomain标记一个特定的属性



如果我这样做,我枚举程序中的所有类型:

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);

相关内容

  • 没有找到相关文章

最新更新