Say I have an Expression<Func<T,object>>
is it possible to dynamically change the return type based on a Type
variable to be something like Expression<Func<T,int>>
I have the following class:
public class ImportCheck<T> {
public int id { get; set; }
public string Name { get; set; }
public Type Type { get; set; }
public bool Required { get; set; }
public int? MinLength { get; set; }
public int? MaxLength { get; set; }
public string Value { get; set; }
public Expression<Func<T, object>> AssociatedProperty { get; set; }
}
I have a List<ImportCheck<Contact>>
which I loop through and for each one set a property on the Contact
object (the properties are all different types). To enable me to set the property of nested objects I need the result type to be the same as the target type.
If all the properties of the contact were say int
then what I have now would work fine it's the fact that I have a list of different types that is causing me the headache.
This is how I set a sub property:
private static Action<M, R> MakeSet<M, R>(Expression<Func<M, R>> fetcherExp) {
if (fetcherExp.Body.NodeType != ExpressionType.MemberAccess) {
throw new ArgumentException(
"This should be a member getter",
"fetcherExp");
}
// Input model
var model = fetcherExp.Parameters[0];
// Input value to set
var value = Expression.Variable(typeof(R), "v");
// Member access
var member = fetcherExp.Body;
// We turn the access into an assignation to the input value
var assignation = Expression.Assign(member, value);
// We wrap the action into a lambda expression with parameters
var assignLambda = Expression.Lambda<Action<M, R>>(assignation, model, value);
return assignLambda.Compile();
}
This is then called like MakeSet(member)(target,value)
where member is the Expression<Func<T,object>>
target
is the object and value
is the value to set the property to.
The type of the expression is the return type of the function. Required. A list of statements that returns a value by using the Return statement. (See Return Statement .) The type of the value returned is the return type of the function. A lambda expression is a function without a name that calculates and returns a value.
A single expression. The type of the expression is the return type of the function. Required. A list of statements that returns a value by using the Return statement. (See Return Statement .) The type of the value returned is the return type of the function. A lambda expression is a function without a name that calculates and returns a value.
An expression is a sequence of operands and operators that can be evaluated to a single value or method or object or namespace. It can consist of literal values, method invocations, names of variables, names of methods, method parameters or types. Expression can vary from very simple to very complex.
Func<T> denotes a delegate that is pretty much a pointer to a method and Expression<Func<T>> denotes a tree data structure for a lambda expression. I think it explains well about when to use it.
Please find the example below:
public class ReturnTypeVisitor<TSource, TReturnValue> : ExpressionVisitor{
protected override Expression VisitLambda<T>(Expression<T> node)
{
var delegateType = typeof(Func<,>).MakeGenericType(typeof(TSource), typeof(TReturnValue));
return Expression.Lambda(delegateType, Visit(node.Body), node.Parameters);
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Member.DeclaringType == typeof(TSource))
{
return Expression.Property(Visit(node.Expression), node.Member.Name);
}
return base.VisitMember(node);
}
}
Usage:
public class Foo{
public Bar Bar { get; set; }
}
public class Bar { }
Expression<Func<Foo, object>> expression = p => p.Bar;
Expression<Func<Foo, Bar>> stronglyTypedReturnValue = (Expression<Func<Foo, Bar>>)new ReturnTypeVisitor<Foo, Bar>().Visit(expression);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With