2010-09-08 22 views
1

據我瞭解,代表們提供了高性能的反思也許比普通明確的C#代碼慢只有15%。然而,我可以在stackoverflow上找到的所有示例都基於事先通過委託人訪問的方法/屬性類型的知識。屬性get/set代表了運行時反映

鑑於此類現有一類的知識,爲什麼訴諸首先反映代理訪問?

總之反射編碼任務,我面對的是如何實現,就在一類類型的名稱在運行時提供的類屬性未知列表的高性能屬性get/set訪問?我可以編寫反射檢查的基礎知識以生成屬性列表,但是如何爲可能隨機的一組屬性類型連接一組基於委託的訪問器?

假設物業類型僅限於一系列基本DB列類型的答案是,它返回一個case語句:

Func<int> or Func<string> etc? 

編輯-1:我限於NET 3.5的

+1

你正在尋找的typeof(Func鍵<>)。MakeGenericType(myDbType);?或者你是否也需要執行委託?此外,** events **的概念是代表們常用的基於非反射的使用場景。 Enumerable的擴展方法也爲代表/ lambdas的實用程序提供了大量示例。 – 2010-09-08 22:48:53

+0

@Kirk。對於需要通過委託設置者填充的每個類,我需要保存這些設置者的數組。當填充委託設置器的數組時,我需要根據我剛剛通過反射發現的Property類型來製作Delegate。 MakeGenericType()似乎是我缺失的鏈接。 – camelCase 2010-09-09 06:33:21

回答

4

這個解決方案使用表達式樹,因爲它們相當容易編寫,並且它們提供了方便的Compile()方法來獲取可以調用的實際Delegate。我做了Func鍵採取實際的對象(所以Func鍵< T,TResult >而不僅僅是Func鍵<TResult>),這樣你可以從任何實例的屬性值。

編輯:添加二傳手實施爲好。

public class MyClass 
{ 
    public string MyStringProperty { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     PropertyInfo propertyInfo = typeof(MyClass).GetProperty("MyStringProperty"); 
     Delegate getter = CreateGetter(propertyInfo); 
     Delegate setter = CreateSetter(propertyInfo); 
     object myClass = new MyClass(); 
     setter.DynamicInvoke(myClass, "Hello"); 
     Console.WriteLine(getter.DynamicInvoke(myClass)); 
    } 

    public static Delegate CreateGetter(PropertyInfo property) 
    { 
     var objParm = Expression.Parameter(property.DeclaringType, "o"); 
     Type delegateType = typeof(Func<,>).MakeGenericType(property.DeclaringType, property.PropertyType); 
     var lambda = Expression.Lambda(delegateType, Expression.Property(objParm, property.Name), objParm); 
     return lambda.Compile(); 
    } 

    public static Delegate CreateSetter(PropertyInfo property) 
    { 
     var objParm = Expression.Parameter(property.DeclaringType, "o"); 
     var valueParm = Expression.Parameter(property.PropertyType, "value"); 
     Type delegateType = typeof(Action<,>).MakeGenericType(property.DeclaringType, property.PropertyType); 
     var lambda = Expression.Lambda(delegateType, Expression.Assign(Expression.Property(objParm, property.Name), valueParm), objParm, valueParm); 
     return lambda.Compile(); 
    } 
} 

打印出「你好」通過首先使用動態設置器將其設置爲「你好」,然後使用動態吸氣劑,以獲得來自對象的屬性。

+0

@Kirk。謝謝你,這似乎接近我所需要的。我在原來的問題上應該更清楚,財產設置是我的主要編碼任務。我可以從類型delegateType = .. MakeGenericType()中獲取它,然後用標準的Jon Skeet和Marc Gavell在這個主題上貼出你的代碼。我認爲Lambdas不參與代表屬性設置場景? – camelCase 2010-09-09 06:50:58

+0

@camelCase,setter也使用表達式樹/ lambda表達式。看到我更新的答案。 – 2010-09-09 14:53:02

+0

@柯克。感謝setter代碼示例。一個問題Expression.Assign()是一個.Net 4.0根據文檔,發現.Net3.5替代品是我要調查的東西。 – camelCase 2010-09-10 07:17:51