我有史以来第一次真正需要手动进行装配扫描。我偶然发现了C# - how enumerate all classes with custom class attribute?,其中包含
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 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();
我是否应该尝试将这两个结合起来在一次扫描中完成此操作,还是只是落入早期优化? (扫描只会在应用程序启动时执行)
是否有一些不同的方法可以更好地进行方法的扫描,因为方法中的方法远多于程序集中的类型?
答案 0 :(得分: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
答案 1 :(得分:2)
我认为您可以对此进行优化,但这取决于属性在方法和类型上的放置方式。如果您知道在特定程序集中定义了具有特殊属性的所有类型和/或方法,则只能扫描这些程序集。
您还可以定义一些方法,例如:
- IEnumerable<Type> GetAllTypesFromAssemblyByAttribute<TAttribute>(Assembly assembly) where TAttribute : Attribute
- IEnumerable<MethodInfo> GetAllMethodsFromTypeByAttribute<TAttribute>(Type type) where TAttribute : 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>();
}