![](/img/trans.png)
[英]Get property value with Expression without knowing target type at compile time
[英]Setting property without knowing target type at compile time
我想在編譯時不知道對象類型的情況下在對象上設置屬性值; 我希望它快速(即每次都不使用反射); 我知道屬性名稱和類型。
最快的方式(afaik)是使用代表; 所以這就是我到目前為止所擁有的:
class User // this is an example.. Assume I don't know which type this is.
{
public string Name {get;set;}
}
public static Action<object, object> CreatePropertySetter(Type targetType, string propertyName)
{
ParameterExpression targetObjParamExpr = Expression.Parameter(targetType);
ParameterExpression valueParamExpr = Expression.Parameter(targetType.GetProperty(propertyName).PropertyType);
MemberExpression propertyExpr = Expression.Property(targetObjParamExpr, propertyName);
BinaryExpression assignExpr = Expression.Assign(targetObjParamExpr, valueParamExpr);
Action<object, object> result = Expression.Lambda<Action<object, object>>(assignExpr, targetObjParamExpr, valueParamExpr).Compile();
return result;
}
然后我打電話:
User user = new User();
var userNameSetter = CreatePropertySetter(user.GetType(), "Name");
userNameSetter(user, "Bob");
但是,它不喜歡我傳遞User類型對象而不是Object的事實,並且失敗並且“ UserExpression類型'User'不能用於'System.Object'類型的委托參數 。
我是表達樹木的新手,所以有點迷失在這里。 為什么不能將User轉換為對象? 我需要某個演員嗎?
“行動”看起來也不好看; 只返回一個帶參數的委托(User user,string propertyValue)會更好。 再次,不知道如何實現這一目標。 實際上,我已經嘗試過Delegate.CreateDelegate,但它使用.Invoke()方法調用,這很慢(這是唯一的方法嗎?); 與Expression.Lambda(非泛型)相同。
有什么想法嗎 ?
另外,表達樹上有一個好的(比msdn好)文檔嗎? msdn版本確實缺乏細節。
如果你想使用Expression,那么: Convert
......
static void Main()
{
var setter = CreatePropertySetter(typeof (User), "Name");
var obj = new User();
setter(obj, "Fred");
}
public static Action<object, object> CreatePropertySetter(Type targetType, string propertyName)
{
var target = Expression.Parameter(typeof (object), "obj");
var value = Expression.Parameter(typeof (object), "value");
var property = targetType.GetProperty(propertyName);
var body = Expression.Assign(
Expression.Property(Expression.Convert(target, property.DeclaringType), property),
Expression.Convert(value, property.PropertyType));
var lambda = Expression.Lambda<Action<object, object>>(body, target, value);
return lambda.Compile();
}
然而! 你可能想看看FastMember (也可以在NuGet上找到),它可以非常方便地為你提供所有這些(並使用原始的IL來進行愚蠢的瘋狂)。
如果要使用類型化的委托,則需要事先知道類型。 如果您知道類型,可以添加一些通用:
static void Main()
{
var setter = CreatePropertySetter<User,string>("Name");
var obj = new User();
setter(obj, "Fred");
}
public static Action<TType, TValue> CreatePropertySetter<TType, TValue>(string propertyName)
{
var target = Expression.Parameter(typeof (TType), "obj");
var value = Expression.Parameter(typeof (TValue), "value");
var property = typeof(TType).GetProperty(propertyName);
var body = Expression.Assign(
Expression.Property(target, property),
value);
var lambda = Expression.Lambda<Action<TType, TValue>>(body, target, value);
return lambda.Compile();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.