创建属性设置器委托
我已经创建了将属性 lambda 转换为委托的方法:
public static Delegate MakeGetter<T>(Expression<Func<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
public static Delegate MakeSetter<T>(Expression<Action<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
这些方法有效:
Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();
Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();
但无法编译:
Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
MakeSetter 行失败,并显示“无法从用法推断类型参数。请尝试显式指定类型参数。”
我想做的事情可能吗?提前致谢。
I have created methods for converting a property lambda to a delegate:
public static Delegate MakeGetter<T>(Expression<Func<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
public static Delegate MakeSetter<T>(Expression<Action<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
These work:
Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();
Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();
but these won't compile:
Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
The MakeSetter lines fail with "The type arguments cannot be inferred from the usage. Try specifying the type arguments explicitly."
Is what I'm trying to do possible? Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Expression
API 在 .NET 4.0 中支持这一点,但遗憾的是 C# 编译器没有添加任何额外的支持。但好消息是,您可以简单地采用“get”表达式(C# 编译器可以编写)并将其重新编写为“set”表达式。甚至更好;如果您没有 .NET 4.0,则仍然至少有两种通过写为“get”的表达式来执行“set”的方法。
它们都在这里,供参考:
The
Expression
API supports this in .NET 4.0, but sadly the C# compiler doesn't add any extra candy to support. But the good news is that you can trivially take a "get" expression (which the C# compiler can write) and re-write it as a "set" expression.And even better; if you don't have .NET 4.0, there are still at least two other ways of performing a "set" via an expression written as a "get".
Here they all are, for info:
根据我的评论 - 因为链接失效了 - 我已经发布了完整的代码作为问题的答案。 是的,可以按照OP的要求进行操作。这是尼克展示的一个漂亮的小宝石。 Nick 将此页和另一页归功于他的完整解决方案以及性能指标。我在下面提供,而不是只是一个链接。
As per my comments - because links go dead - I have posted the full code as an answer to the question. YES it is possible to do what the OP is requesting. and here is a nice little gem from Nick demonstrating it. Nick credits this page and another page for his complete solution along with performance metrics. I provide that below instead of just a link.
Action
表示一个委托,它采用一个T
类型的参数并且不返回任何内容。您提供给MakeSetter
的 lambda 表达式表示不带参数并返回SomeClass.SomeProperty
或someObject.SomeProperty
的委托。您收到的错误消息是由于编译器无法从您传递到
MakeSetter
方法的 lambda 表达式中推断出类型,因为您传递的内容以及该方法所期望的内容不同步。Action<T>
represents a delegate that takes one parameter of typeT
and returns nothing. The lambda expressions you provide toMakeSetter
represent delegates that take no parameter and return eitherSomeClass.SomeProperty
orsomeObject.SomeProperty
.The error messages you're getting are due to the fact that the compiler cannot infer the types from the lambda expressions you're passing into the
MakeSetter
method because what you've passed and what the method is expecting are not in sync.您的
MakeSetter
需要一个Action
并且您正在向它传递一个Func
(() => someObject .SomeProperty
)。请尝试以下操作:编辑看起来不行将语句 lambda 转换为表达式 。这是一种无需表达式的迂回方式 - 直接向委托人发送:
Your
MakeSetter
is expecting anAction<T>
and you are passing it aFunc<T>
(() => someObject.SomeProperty
). Try the following:EDIT Doesn't look like you can convert statement lambdas into expressions. This is somewhat of a round about way to do it without expressions - straight to delegates: