C# 为自定义属性扫描所有类和方法的最佳实践

C# 为自定义属性扫描所有类和方法的最佳实践,c#,reflection,performance,C#,Reflection,Performance,这是我有史以来第一次真正需要自己手动进行组装扫描。我遇到了让我陷于困境的人 var typesWithMyAttribute = (from assembly in AppDomain.CurrentDomain.GetAssemblies() from type in assembly.GetTypes() let attributes = type.GetCustomAttributes(typeof(SomeAttribute), true) where attri

这是我有史以来第一次真正需要自己手动进行组装扫描。我遇到了让我陷于困境的人

var typesWithMyAttribute =
(from assembly in AppDomain.CurrentDomain.GetAssemblies()
    from type in assembly.GetTypes()
    let attributes = type.GetCustomAttributes(typeof(SomeAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = type, Attributes = attributes.Cast<SomeAttribute>() })
    .ToList();
var-typesWithMyAttribute=
(来自AppDomain.CurrentDomain.GetAssemblys()中的程序集)
来自程序集中的类型。GetTypes()
let attributes=type.GetCustomAttributes(typeof(SomeAttribute),true)
其中attributes!=null&&attributes.Length>0
选择新{Type=Type,Attributes=Attributes.Cast()})
.ToList();
这足够简单,可以扩展到方法级别

var methodsWithAttributes =
    (from assembly in AppDomain.CurrentDomain.GetAssemblies()
    from type in assembly.GetTypes()
    from method in type.GetMethods()
    let attributes = method.GetCustomAttributes(typeof(SomeAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = type, Method = method, 
            Attributes = attributes.Cast<SomeAttribute>() })
    .ToList();
var方法属性=
(来自AppDomain.CurrentDomain.GetAssemblys()中的程序集)
来自程序集中的类型。GetTypes()
来自类型为.GetMethods()的方法
let attributes=method.GetCustomAttributes(typeof(SomeAttribute),true)
其中attributes!=null&&attributes.Length>0
选择新{Type=Type,Method=Method,
Attributes=Attributes.Cast()})
.ToList();
我应该试着将这两种方法结合起来,在一次扫描中完成这项工作,还是只是进入早期优化阶段?(扫描仅在应用程序启动时执行)


由于程序集中的方法比类型多得多,因此扫描方法时是否有更优化的方法?

我认为您可以对此进行优化,但这取决于属性如何放置在方法和类型上。如果知道所有具有特殊属性的类型和/或方法都是在特定程序集中定义的,则只能扫描这些程序集

您还可以定义一些方法,如:

 - IEnumerable<Type> GetAllTypesFromAssemblyByAttribute<TAttribute>(Assembly assembly) where TAttribute : Attribute
 - IEnumerable<MethodInfo> GetAllMethodsFromTypeByAttribute<TAttribute>(Type type) where TAttribute : Attribute
-IEnumerable GetAllTypesFromAssemblyByAttribute(程序集),其中TaAttribute:Attribute
-IEnumerable GetAllMethodsFromTypeByAttribute(类型类型),其中TaAttribute:Attribute
并在主扫描方法中使用这些方法

因此,您的结果扫描方法可能如下所示:

private void ScanAndDoSmth<TAttribute>(IEnumerable<Assembly> assemblies)
where TAttribute : Attribute
{
    var result =
        from assembly in assemblies
        from type in GetAllTypesFromAssemblyByAttribute<TAttribute>(assembly)
        let attributes = type.GetCustomAttributes(typeof(TAttribute), true)
        where attributes != null && attributes.Length > 0
        select new { Type = type, Attributes = attributes.Cast<TAttribute>();
}
private void scannanddosmth(IEnumerable assemblies)
其中:属性
{
var结果=
从程序集中的程序集
从GetAllTypesFromAssemblyByAttribute(程序集)中的类型
let attributes=type.GetCustomAttributes(typeof(tatAttribute),true)
其中attributes!=null&&attributes.Length>0
选择新的{Type=Type,Attributes=Attributes.Cast();
}

反射非常慢…

我认为你已经做到了最基本的部分。我建议你稍微修改一下你的代码,以避免发生额外的完全扫描

如果你必须不止一次地这样做,我也建议你考虑在任何时间段内缓存结果。

有点像这样的伪代码:

... (optional caches) ...
IDictionary<Type, IEnumerable<Attributes>> typeAttributeCache = new ...
IDictionary<MethodInfo, IEnumerable<Attributes>> methodAttributeCache = new ...

... (in another method or class) ...
foreach assembly in GetAssemblies()
  foreach type in assembly.GetTypes()        
    typeAttributes = typeAttributeCache.TryGet(...) // you know the correct syntax, trying to be brief

    if (typeAttributes is null)
      typeAttributes = type.GetCustomAttributes().OfType<TypeImLookingFor>();
      typeAttributeCache[type] = typeAttributes;

    foreach methodInfo in type.GetMethods()        
      methodAttributes = methodAttributeCache.TryGet(...) // same as above

      if (methodAttributes is null)
        methodAttributes = methodInfo.GetCustomAttributes().OfType<TypeImLookingFor>();
        methodAttributeCache[type] = methodAttributes;

    // do what you need to do
…(可选缓存)。。。
IDictionary typeAttributeCache=新建。。。
IDictionary methodAttributeCache=新建。。。
…(在另一个方法或类中)。。。
GetAssemblys()中的foreach程序集
程序集中的foreach类型。GetTypes()
typeAttributes=typeAttributeCache.TryGet(…)//您知道正确的语法,尽量简短
if(typeAttributes为null)
typeAttributes=type.GetCustomAttributes().OfType();
typeAttributeCache[type]=类型属性;
类型为.GetMethods()的foreach methodInfo
methodAttributes=methodAttributeCache.TryGet(…)//同上
if(methodAttributes为null)
methodAttributes=methodInfo.GetCustomAttributes().OfType();
methodAttributeCache[type]=methodAttributes;
//做你需要做的事

我打赌枚举程序集和类型将比查找和实例化属性快得多,因此缓存程序集和类型将毫无意义。