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.
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.
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:
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.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: