0

xml を解析し、その xml から指定された型のオブジェクトを作成するメソッドがあります。これはすべて、すべての型に共通のメソッドを持つようにジェネリックを使用して行われます。

私の問題は、(名前ではなく) タイプ名を使用して、さまざまなクラスのプロパティを検索したいということです。プロパティのタイプが「type1」であるとしましょう。次に、クラス定義の一部を以下で宣言します。

class foo1
{
  type1 prop1{get;set;}
}

class foo2
{
  foo1 prop2{get;set;}
}

class foo3:foo2
{
  type2 prop3{get;set;}
}

上記で宣言されたすべてのクラスについて、オブジェクトを作成すると、上記のクラスの各インスタンスの型付きプロパティにアクセスしたい、つまり、クラスのオブジェクトからtype1宣言されたプロパティの値を取得できるはずです。クラスが増える可能性があるため、これを行う一般的な方法が本当に必要です。type1foo1foo2foo3

4

1 に答える 1

1

ほぼこれを行う1 つの方法を次に示します。欠けているのは、リフレクションを使用すると、BindingFlags.FlattenHierarchy が親クラスのプライベート メソッドを返さないことです。これらのタイプを保護またはパブリックとしてマークすると、これが解決されます。(基本クラスを手動でトラバースして、プライベート メンバーを読み取ることもできます。)

特定の型のプロパティを宣言するアセンブリ内のすべての型を検索する場合は、次のようなメソッドを記述できます。

// using System.Reflection

public IEnumerable<Type> GetTypesWithPropertyOfType(Assembly a, Type t)
{
    BindingFlags propertyBindingFlags = BindingFlags.Public 
                                       | BindingFlags.NonPublic 
                                       | BindingFlags.Instance 
                                       | BindingFlags.FlattenHierarchy;

    // a property is kept if it is assignable from the type
    // parameter passed in            
    MemberFilter mf = (pi, crit)=>
          (pi as PropertyInfo)
          .PropertyType
          .IsAssignableFrom(t);

    // a class is kept if it contains at least one property that
    // passes the property filter.  All public and nonpublic properties of
    // the class, and public and protected properties of the base class,
    // are considered
    Func<Type, bool> ClassFilter = 
        c=>c.FindMembers(MemberTypes.Property, propertyBindingFlags, mf, null)
            .FirstOrDefault() != null;

    // return all classes in the assembly that match ClassFilter
    return
        a.GetTypes()
        .Where(c=>c.IsClass)
        .Where(ClassFilter);
}

type のプロパティを定義または継承する実行中のアセンブリ内のクラスを見つけるには、次のtype1ように呼び出します。

    var v = GetTypesWithPropertyOfType(
           Assembly.GetExecutingAssembly(),
           typeof(type1));

    foreach (var n in v) Console.WriteLine(n.FullName);

これにより、foo1 が出力されます。foo クラスを定義するコードを (a)foo1.prop1公開または保護するように変更し、(b)foo2から継承するように変更するfoo1と、上記のコードは次のように出力されます。

foo1
foo2
foo3

予想通り。

于 2012-01-16T11:10:14.523 に答える