特定の属性でマークされたAppDomainのすべてのタイプを取得する最も効率的な方法は?

c# reflection
特定の属性でマークされたAppDomainのすべてのタイプを取得する最も効率的な方法は?

これを行う場合、プログラムのすべてのタイプを列挙します。

List attributes=new List() ;
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    foreach (Type type in assembly.GetTypes())
    {
        attributes.AddRange(
                            type.GetCustomAttributes(false)
                            .OfType()
                            .ToList());
    }
}
NET dllに付属するメタデータは、次のようなことができるようにインデックスが付けられていますか?
List attributes = typeof(SerializableAttribute)
                                         .GetClassesIAmDefinedOn();

私が検討していない別のオプションはありますか?

(SerializableAttributeは単なる例です)

  3  0


ベストアンサー

まあ、少なくともLINQを使用し、少なくとも「IsDefined」を使用すると、コードが_nicer_になります(属性ではなく型を取得します…​)

var types = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
             from type in assembly.GetTypes()
             where Attribute.IsDefined(type, typeof(SerializableAttribute))
             select type).ToList();

さて、あなたは_効率について尋ねました-これにはどれくらい時間がかかりますか? どれくらい時間がかかりますか? これをよく呼んでいますか? (それは奇妙に思えます。)

また、既にロードされているアセンブリのみが含まれていることに注意してください。まだロードされていない参照アセンブリがある可能性があります。それが拾われないことは重要ですか?

8


ここで使用する最も効率的な_generally_は Attribute.IsDefined(…​)`です。ただし、 `[Serializable] _の特定のケースでは、 `type.IsSerializable`はより高速です(実際には属性として保存されません)この1つのケースでは、コンパイラーで特別な処理が行われ、CLIフラグにマッピングされます)。

7


いいえそうではありません。 GetCustomAttributesに注意してください。 非常に高価であり、効果的にキャッシュされません。 AppDomain.Current.Domain.GetAssembliesも非常に高価です。

このようなことをするために、辞書にキャッシュを保持します

var cache = new Dictionary();

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
    var attributes = new List();
    foreach (Type type in assembly.GetTypes())
    {
        attributes.AddRange(
                            type.GetCustomAttributes(false)
                            .OfType()
                            .ToList());
    }
    cache[assembly] = attributes.ToArray();
}

2


あなたはどちらかをすることができます:

var assem = // get assembly:
var types = assem.GetTypes().Where(t => t.IsDefined(typeof(SerializableAttribute)));

または、他の方法でやりたい場合:

public static IEnumerable WhereDefinedOn(this Type type, IEnumerable 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);

1


タイトルとURLをコピーしました