如何爲可以處理未知類型的函數創建lambda表達式?對不起,我知道這個問題很模糊,我很難形成它。我只希望你有一分鐘的時間,並閱讀我的故事,這應該會讓事情變得更加清晰。如何創建可以處理或投射未知類型的lambda表達式?
我的目標是使用預定義的數據合約將字符串值數組反序列化爲對象。數據合同的成員有一個職位編號。反序列化器的簡單工作是將值映射到數據成員(在進行適當的類型轉換之後)並構建對象。
問題是,反序列化性能很糟糕!運行VS Profiler後,我發現用於填充對象成員的PropertyInfo.SetValue()花費了大量時間。我的程序必須在任何給定時間反序列化數千個對象。數據合同通常有100個成員。所以我們正在對每個1000個對象說100,000次SetValue()調用,並且正在拖動。下面是調用的SetValue的樣本:
// for each data contract type
// go through each property and set the value
foreach(PropertyInfo pi in pis)
{
object data = convertStringToMemberType(pi, attributeArray, valueStringArray);
pi.SetValue(objectToBuild, data, null);
}
後來我發現this page from Unknown Recipes,其中有一個希望解決這個性能問題。 它看起來像我需要使用編譯的lambda表達式來替換SetValue,但我遇到了鑄造問題。以上面的鏈接爲例,我現在已經替換了SetValue()。替換項是Action委託,它們是編譯的lambda表達式。
首先,我擴展了PropertyInfo類。
public static class PropertyInfoExtensions
{
public static Action<object, object> GetValueSetter(this PropertyInfo propertyInfo)
{
var instance = Expression.Parameter(propertyInfo.DeclaringType, "i");
var argument = Expression.Parameter(typeof(object), "a");
var setterCall = Expression.Call(
instance,
propertyInfo.GetSetMethod(),
Expression.Convert(argument, propertyInfo.PropertyType));
return (Action<object, object>)Expression.Lambda(setterCall, instance, argument).Compile();
}
}
然後我建了一個Dictionary<PropertyInfo, Action<object, object>
對象,它關係到每個PropertyInfo對象到其相應的Action委託。這樣我就可以「緩存」已編譯的lambda表達式並在一批反序列化中重用它。這是我現在該怎麼稱呼它:
foreach(PropertyInfo pi in pis)
{
object data = convertStringToMemberType(pi, attributeArray, valueStringArray);
var setValueDelegate = _actionDelegateDict[pi];
setValueDelegate(objectToBuild, data);
}
不過,我收到以下異常:
Unable to cast object of type 'System.Action`2[Test.DataContract1,System.Object]' to type 'System.Action`2[System.Object,System.Object]'.
這裏DataContract1是我試圖建立對象的類型。它只在運行時才知道,這與Unknown Recipes的例子中的情況不同,在這種情況下,類型在編譯時已知。你將如何去做這個lambda表達式的工作?
非常感謝你的時間!
這不是Java。 – Jeffrey
有趣的是,lamba表達式將成爲Java 8的一個特性。 – arshajii
對不起,我沒有意識到我需要標記「c#」。感謝您的關注! – Zoomzoom