2012-12-21 59 views
5

這是我第一次使用Reflection.Emit。我正在爲提供的對象動態構建代理。代理將通過任何public屬性訪問到提供的對象。我收到的錯誤是:使用Reflection從另一個對象獲取屬性值。發送

上的屬性訪問對象「ProxyObject」「AccessorName」發生以下異常: 嘗試通過方法「ProxyObject.get_AccessorName()」來訪問方法 「NS.CoreObject.get_AccessorName ()失敗。

從我可以假設和收集,這將是由於自動生成屬性getter方法是私人和隱藏的。但是我如何使用MethodBuilder解決這個問題?

根據崗位在Create DynamicMethod to assign value to a property?,您可以通過聲明被「關聯」與目標模塊的方法DynamicMethod的做到這一點,但我需要建立一個完整的類。是否有可以通過Reflection.Emit實現的等效「關聯」?

這是我正在嘗試執行的一項基本操作,所以我確信這是直截了當的,簡單的,我不知道。

+0

That's MethodAccessException。這聽起來像是該財產事實上並不公開。首先在C#中完成這項工作,從中得到的IL對於你的排放代碼也會非常有幫助。 –

+0

當然,當你的課堂不公開時,公共財產並不意味着什麼。在我的腦海中,這個類型被定義在同一個模塊中。又一個*「我在這個上浪費了幾個小時?」*時刻。 – redman

回答

9

With MethodBuilder:you can not。你需要遵守通常的無障礙規則。但是,您可以通過DynamicMethod作弊,這允許您假裝(如果您有足夠的訪問權限)您正在創建的方法實際上是給定類型(或給定模塊等)的靜態方法。這意味着你可以自由訪問私有狀態,例如:

using System; 
using System.Reflection; 
using System.Reflection.Emit; 

public class Foo 
{ 
    public Foo(int bar) 
    { 
     Bar = bar; 
    } 
    private int Bar { get; set; } 
} 
static class Program { 
    static void Main() 
    { 
     var method = new DynamicMethod("cheat", typeof(int), 
      new[] { typeof(object) }, typeof(Foo), true); 
     var il = method.GetILGenerator(); 
     il.Emit(OpCodes.Ldarg_0); 
     il.Emit(OpCodes.Castclass, typeof(Foo)); 
     il.Emit(OpCodes.Callvirt, typeof(Foo).GetProperty("Bar", 
      BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic 
      ).GetGetMethod(true)); 
     il.Emit(OpCodes.Ret); 
     var func = (Func<object, int>)method.CreateDelegate(
      typeof(Func<object, int>)); 

     var obj = new Foo(123); 
     Console.WriteLine(func(obj)); 
    } 
} 

如果你是取得該財產的價值,還應當指出的是,Delegate.CreateDelegate可以自動做同樣的,通過吸氣方法:

var method = typeof(Foo).GetProperty("Bar", 
    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) 
    .GetGetMethod(true); 
var func = (Func<Foo, int>) 
    Delegate.CreateDelegate(typeof(Func<Foo, int>), method); 
+0

有道理(也很有創意)。如果我通過TypeBuilder構建一個類型,我能夠將由答案生成的IL轉換爲TypeBuilder構建的類型嗎?還是兩個互斥? – redman

+0

@redman獲得相同的IL將無濟於事。 TypeBuilder仍然*限於標準的可訪問性。在IL級別,你可以*詢問**任何事情**:它在第一次使用時仍會被檢查。 –

+0

我剛剛意識到我的問題的一部分是模棱兩可的。我嘗試訪問的屬性是* public *。這是自動生成的訪問器,不是。 (我更新了我的問題以反映這一點。)因此,考慮到這一點,通過MethodBuilder使用另一個對象的屬性更容易嗎? – redman

相關問題