2011-07-15 8 views
2

これが可能かどうかを知りたいと思います。私は、自動実装されたベースクラスのプロパティをオーバーライドしました。私はデフォルト設定に対して "不足している"プロパティを解決するためにオーバーライドのロジックを提供しました。reflection- base.Propertyをthis.Propertyとして使用してベースクラスプロパティ値を取得する

ここで、リフレクションを使用して、デフォルト値が使用されているかどうか、または実際の値が使用されているかどうかを確認したいとします。つまり、base.Propertyがnullであるかどうかを確認する必要がありますが、リフレクションを使用します。これは機能しません、単にサブクラスの値を取得します(デフォルトでは解決されるため、nullではありません)。

var property = this.GetType().GetProperty(e.PropertyName); 
if(property.GetValue(this, null) == null)) 
    OnPropertyChanged(e.PropertyName); 

も試してみました:

var property = this.GetType().BaseType.GetProperty(e.PropertyName); 
if(property.GetValue(this, null) == null)) 
    OnPropertyChanged(e.PropertyName); 

は、基本クラスの値にアクセスするためにリフレクションを使用して、それは可能ですか?

UPDATE:

コメントからのアドバイスに続いて、私はキックのために、以下のことを試してみました。

var method1 = this.GetType().BaseType.GetMethods().First(x => x.Name.Contains(e.PropertyName)); 
var method = this.GetType().BaseType.GetProperty(e.PropertyName).GetGetMethod(); 
var methodValue = method1.Invoke(this, null); 

同時にbase.Property戻るヌルながら、これらの両方は、依然として、「由来する」の値を返します。

+0

プロパティは仮想ですか? – Tigran

+0

@Tigranはい、そうでなければ、私はそれを無効にすることはできませんでしたか? – Max

+0

あなたは "新しい"を使用することができます、それは.. – Tigran

答えて

5

基本的にcallvirtではなくcall命令を使用して、独自のILを放出することなくそれを行う方法はありませんが、知る限りでは可能です。

デザインの作業を行うためにこれらの長さに移動する必要がある場合は、おそらくどこかで何か間違ったことをしているという印があることに注意してください。

とにかく、ここには例があります。 (簡略化のためエラーチェックなど省略)

var derived = new DerivedClass(); 
Console.WriteLine(derived.GetBaseProperty("Prop")); // displays "BaseProp" 

// ... 

public class BaseClass 
{ 
    public virtual string Prop { get; set;} 
} 

public class DerivedClass : BaseClass 
{ 
    public override string Prop { get; set;} 

    public DerivedClass() 
    { 
     base.Prop = "BaseProp"; 
     this.Prop = "DerivedProp"; 
    } 

    public object GetBaseProperty(string propName) 
    { 
     Type t = this.GetType(); 
     MethodInfo mi = t.BaseType.GetProperty(propName).GetGetMethod(); 

     var dm = new DynamicMethod("getBase_" + propName, typeof(object), new[] { typeof(object) }, t); 

     ILGenerator il = dm.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Call, mi); 
     if (mi.ReturnType.IsValueType) il.Emit(OpCodes.Box, mi.ReturnType); 
     il.Emit(OpCodes.Ret); 

     var getBase = (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>)); 
     return getBase(this); 
    } 
} 
+0

情報をいただきありがとうございますが、正しく言うように、これを行う必要があるのはおそらく、あなたがデザインのどこかで間違った方向に回ったということです)。そしてそれは私がそれを行うことがそれほど簡単ではないことを理解するのを容易にします。 – InBetween

+0

これは、バッキングフィールドがないためにのみ機能します。あなたは単に2つのリテラルを格納しています。 OPは、基本プロパティが自動実装されるように指定しました。 –

+0

@Charles:これは、私が十分な睡眠を取らず(適切にテストしていない)、このようなコードを書くために得られるものです。うまくいけばうまくいけばいいのですが、私はこの例を使って自動プロパティも更新しました。 – LukeH

1

AFAIKできないと思います。 realオブジェクトの型は派生型で、仮想メソッドのメソッドによって、どの型インスタンス(実際の型または基本型)を呼び出しても、オーバーライドされた実装が得られます。

この作業を他の方法で行うことは、少なくとも私にとって予期しない動作です。

EDIT:私はそれをベースimplentationを取得することが実際に可能かどうかを確認するために、次の試してみました:

Type baseType = this.GetType().BaseType; 
var methodInfo = baseType.GetMethod("Foo"); 
string foo = methodInfo.Invoke(this, null); //Derived type implementation 

これはさえbaseタイプMethodInfo反射によってメソッドを呼び出すとすることができることを意味しますオーバーライドを解決し、派生した実装を返します。だから、あなたがしようとしていることは、リフレクションでは不可能だと思うし、少なくとも私はそれをやり遂げる方法が見えない。

+0

MSDNから:派生クラスでオーバーライドされたメソッドを呼び出すために、基本クラスのMethodInfoオブジェクトを使用できないことに注意してください。 – Jeff

+0

@ JeffN825:私はこれで間違っているかもしれないと考えましたが、本当に可能かどうかをテストしなければならないので、私は答えを保持します。派生型による基底実装へのアクセスは、派生した型の実装を破る方法であり、その中から何が出てくるのかを知っている人です。とにかく、反射の欠点の1つは、あなたができるべきではないことをすることができるということですが、その有用性のために生きることができます。この場合、私の答えは正しいと思っています。 – InBetween

+0

はい、私はあなたが何を意味しているか見ていますが、base.Propertyを使って*可能であるので、Reflect-Ninjaのやり方もあると思っていました。 – Max