-1

コードでを定義する際に問題がありTypeます。Abcから始めましょう。

public partial class Abc {
    public static String AbcName="wtf";

    public String Name {
        get;
        set;
    }
}

よし、Abc完了。あとはテスト用の授業です。のインスタンスを持つオブジェクトまたは型を返す必要がありますMyClass

    public partial class MyClass {
        public const BindingFlags
            Universal=BindingFlags.NonPublic|BindingFlags.Public,
            WithObject=Universal|BindingFlags.Instance,
            WithClass=WithObject|BindingFlags.Static,
            ForGive=Universal|BindingFlags.SetProperty|BindingFlags.SetField,
            ForGet=Universal|BindingFlags.GetProperty|BindingFlags.GetField,
            ForDo=BindingFlags.InvokeMethod|WithObject|WithClass;

        public MyClass GetTypeImpl() {
            if(null!=target)
#if TARGET_AS_TYPE
                return new MyClass(target as Type??target.GetType());
#else
                return new MyClass(target.GetType());
#endif
            else
                return new MyClass(typeof(object));
        }

        public object GetValue(String name) {
            var invokeAttr=ForGet|WithClass;
            var type=(Type)this.GetTypeImpl().target;
            return type.InvokeMember(name, invokeAttr, default(Binder), target, default(object[]));
        }

        public MyClass(object x) {
            this.target=x;
        }

        public object target;
    }

コードは私のクラスを表すためのものであることに注意してください。GetValuein real code は内部的に呼び出され、消費するコードは の型以外のオブジェクトを取得することはありませんMyClass。つまり、実際のコードでは、 のすべてのメソッドMyClassが実際に のインスタンスを返しますMyClass。ここでTARGET_AS_TYPE、この質問のポイントである を使用した条件付きコンパイルを確認します。

次のテストコードを検討してください

    public partial class TestClass {
        public static void TestMethod() {
            var abc=
                new Abc {
                    Name="xyz"
                };

            var x=new MyClass(abc);
            var abcName=x.GetValue("Name");
            var y=new MyClass(x.GetTypeImpl().target);

#if TARGET_AS_TYPE
            var wtf=y.GetValue("AbcName");
            var fullName=y.GetValue("FullName"); // exception thrown
#else
            var fullName=y.GetValue("FullName"); 
            var wtf=y.GetValue("AbcName"); // exception thrown
#endif
        }
    }

定義するかどうかにかかわらTARGET_AS_TYPEず、テストは常に 2 行目の#ifor#elseifブロックで例外をスローします。Typeorのせいだと思いますが、RuntimeType定義できません。それで、それを(GetTypeImplで)修正して、条件付きコンパイルなしで常に機能させる方法は

次の方法は制限されているか、効果がありません。

  • の使用BindingFlags.FlattenHierarchy- 機能しない
  • ジェネリックの宣言MyClass<T>- 機能しない
  • のインスタンスで型やオブジェクトをワープしないでMyClassください - あなたは私をからかっているに違いありません...
4

1 に答える 1

3

次のコードを検討してください。

Abc a = new Abc { Name = "a" };

Type t = a.GetType();

BindingFlags staticField = BindingFlags.Static | 
                           BindingFlags.Public | 
                           BindingFlags.GetField;
BindingFlags instanceProperty = BindingFlags.Instance | 
                                BindingFlags.Public | 
                                BindingFlags.GetProperty;

//prints a
t.InvokeMember("Name", instanceProperty, default(Binder), a, null);
//prints wtf
t.InvokeMember("AbcName", staticField, default(Binder), a, null);
//throws an exception as there is no member FullName in MyClass
t.InvokeMember("FullName", instanceProperty, default(Binder), a, null);

Type tt = t.GetType();
//prints t.FullName, that is YourNamespace.Abc
tt.InvokeMember("FullName", instanceProperty, default(Binder), t, null);

それはあなたのIMOが抱えている問題を示しています。クラスのメンバーがないため、リフレクションを介してクラスを記述するTypeタイプのオブジェクトを介してクラスのメンバーにアクセスすることはできません。TypeMyClassMyClass

Typeクラスを記述するオブジェクトType(つまり)を使用して、リフレクションを介してa.GetType().GetType()そのメンバー(ここ)にアクセスし、クラスを記述するFullNameタイプのオブジェクトをに渡す必要があります。TypeMyClassInvokeMember


コメントに基づいて、次のタイプのオブジェクトに同じ例を投稿したいと思いますSystem.Object

object o = new object();
Type ot = o.GetType();

BindingFlags instanceMethod = BindingFlags.Instance | 
                                BindingFlags.Public | 
                                BindingFlags.InvokeMethod;

//prints System.Object
ot.InvokeMember("ToString", instanceMethod, default(Binder), o, null);
//throws an exception, 
//as there is obviously also no FullName in class System.Object
ot.InvokeMember("FullName", instanceProperty, default(Binder), o, null);
于 2013-01-29T00:19:17.420 に答える