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

Chr*_*sic 5 c# reflection performance

我有史以来第一次真正需要手动进行装配扫描.我遇到了C# - 如何使用自定义类属性枚举所有类?这让我很开心

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();
Run Code Online (Sandbox Code Playgroud)

这很简单,可以扩展到方法级别

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();
Run Code Online (Sandbox Code Playgroud)

我是否应该尝试将这两个结合起来在一次扫描中完成此操作,还是只是落入早期优化?(扫描只在app开始时执行)

是否存在一些不同的方法,这些方法对于方法的扫描更为理想,因为组件中的方法多于类型?

小智 3

反映速度很慢...

我想你已经掌握了基础知识。我建议您稍微更改代码以避免发生额外的完整扫描。

如果您必须多次执行此操作,我还建议您考虑在适当的时间段内缓存结果。

像这样的伪代码:

... (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
Run Code Online (Sandbox Code Playgroud)