2011-03-10 9 views
5

初めて実際に手動でアセンブリをスキャンする必要がありました。私は、メソッドレベルにカスタム属性のすべてのクラスとメソッドをスキャンするためのベストプラクティス

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

で私を設定C# - how enumerate all classes with custom class attribute?に出くわした私は、単一のスキャンでこれを行うためにこれらの2を結合しようとする必要があり、または初期の最適化に落としただけですか? (スキャンはアプリケーションの起動時にのみ実行されます)

アセンブリの型よりはるかに多くのメソッドがあるので、メソッドのスキャンのために最適な方法がありますか?

+0

私はアセンブリおよび種類を列挙すると、アセンブリと型をキャッシュすることであるように、発見し、あなたの属性をインスタンス化するよりもはるかに高速になるだろうことを賭けるつもりです無意味になるだろう。 – Gabe

答えて

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 
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>(); 
} 
関連する問題