我怎样才能使这项工作有深刻的性能 [英] How can I make this work with deep properties
问题描述
由于以下code ...
Given the following code...
class Program {
static void Main(string[] args) {
Foo foo = new Foo { Bar = new Bar { Description= "Martin" }, Name = "Martin" };
DoLambdaStuff(foo, f => f.Name);
DoLambdaStuff(foo, f => f.Bar.Description);
}
static void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression) {
// Set up and test "getter"...
Func<TObject, TValue> getValue = expression.Compile();
TValue stuff = getValue(obj);
// Set up and test "setter"...
ParameterExpression objectParameterExpression = Expression.Parameter(typeof(TObject)), valueParameterExpression = Expression.Parameter(typeof(TValue));
Expression<Action<TObject, TValue>> setValueExpression = Expression.Lambda<Action<TObject, TValue>>(
Expression.Block(
Expression.Assign(Expression.Property(objectParameterExpression, ((MemberExpression)expression.Body).Member.Name), valueParameterExpression)
), objectParameterExpression, valueParameterExpression
);
Action<TObject, TValue> setValue = setValueExpression.Compile();
setValue(obj, stuff);
}
}
class Foo {
public Bar Bar { get; set; }
public string Name { get; set; }
}
class Bar {
public string Description{ get; set; }
}
到呼叫DoLambdaStuff(FOO,F =&GT; f.Name)
工作正常,因为我访问一个浅浅的财产,但在调用 DoLambdaStuff(FOO,F =&GT; f.Bar.Description)
失败 - 尽管在创建的getValue
功能正常工作,创造在 setValueEx pression
失败,因为我试图访问该对象的深层属性。
The call to DoLambdaStuff(foo, f => f.Name)
works ok because I am accessing a shallow property, however the call to DoLambdaStuff(foo, f => f.Bar.Description)
fails - although the creation of the getValue
function works fine, the creation of the setValueExpression
fails because I am attempting to access a deep property of the object.
任何人都可以请帮我修改,这样我可以创建 setValueEx pression
深性能以及浅?
Can anybody please help me to modify this so that I can create the setValueExpression
for deep properties as well as shallow?
感谢。
推荐答案
您需要考虑的事实,你的前pression.Body已经重新presenting要设置的属性优势。这意味着您可以使用EX pression.Body为左手侧的分配前pression:
You need to take advantage of the fact that your expression.Body is already representing the property you want to set. This means you can use expression.Body as the left-hand-side in your assignment expression:
public static void Main(string[] args)
{
Foo foo = new Foo { Bar = new Bar { Name = "Martin", Buzz = new Fiz() { Name = "Carl" }}, Name = "Martin" };
DoLambdaStuff(foo, f => f.Bar.Name, "Dennis");
DoLambdaStuff(foo, f => f.Bar.Buzz.Name, "Dennis");
Console.WriteLine(foo.Bar.Name);
Console.WriteLine(foo.Bar.Buzz.Name);
}
static void DoLambdaStuff<TObject, TValue>(TObject obj, Expression<Func<TObject, TValue>> expression, TValue valueToSet)
{
// Getter.
Func<TObject, TValue> getter = expression.Compile();
TValue stuff = getter(obj);
ParameterExpression pObj = expression.Parameters[0];
ParameterExpression pValue = Expression.Parameter(typeof (TValue), "value");
var setterBlock = Expression.Block(
Expression.Assign(expression.Body, pValue)
);
var setterExpression = Expression.Lambda<Action<TObject, TValue>>(setterBlock, pObj, pValue);
Action<TObject, TValue> setter = setterExpression.Compile();
// Test
setter(obj,valueToSet);
}
这篇关于我怎样才能使这项工作有深刻的性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!