Ho un'espressione di espressione dell'albero
var lambdaExpr
che quando compilato genererà
Action<Type,int>
Comunque vorrei avvolgere questo e generare un'espressione che, una volta compilata, genererà
Action<object, int>
e dovrò forzare un cast sul primo argomento all'azione per convertirlo prima di passarlo al lambda originale
object --- cast ---> Type
che quando viene eseguito sarà ovviamente attraverso un'eccezione di runtime se il cast non è possibile.
Come faccio a racchiudere l'espressione dell'albero delle espressioni originali in quella nuova?
Nello specifico ho bisogno di aggiungere del codice extra dove indicato di seguito per ottenere i tipi corretti.
private static Action<object, TProp> GenerateSetter<TProp>(Type type, string propertyName )
{
var property = type.GetProperty
(propertyName, BindingFlags.Public
| BindingFlags.Instance
| BindingFlags.NonPublic);
MethodInfo setterMethodInfo = property.SetMethod;
ParameterExpression paramo = Expression.Parameter(type, "param");
ParameterExpression parami = Expression.Parameter(typeof(TProp), "newvalue");
MethodCallExpression methodCallSetterOfProperty =
Expression.Call(paramo, setterMethodInfo, parami);
Expression setPropertyValueExp =
Expression.Lambda(methodCallSetterOfProperty, paramo, parami);
// This line below fails because setPropertyValueExp is an
// Action with first argument
// being the type passed in at runtime. I need to wrap it with a lambda that
// casts the object to the correct type.
var setPropertyValueLambda =
( Expression<Action<object, TProp>> ) setPropertyValueExp;
var setterFunc = setPropertyValueLambda.Compile();
return setterFunc;
}
Devi prendere l' Action<Type,int>
lambda e generare Action<object,int>
lambda che esegue il cast e la chiama:
var p=Expression.Parameter(typeof(object));
var conversion=Expression.Convert(p,type);
var call=Expression.Invoke(setPropertyValueExp,conversion);
var lambda=Expression.Lambda(call,p);
return lambda.Compile() as Action<object,int>;
Dovresti aggiungere il cast alla tua espressione (usando Expression.Convert
):
private static Action<object, TProp> GenerateSetter<TProp>(Type type, string propertyName )
{
var property = type.GetProperty
(propertyName, BindingFlags.Public
| BindingFlags.Instance
| BindingFlags.NonPublic);
MethodInfo setterMethodInfo = property.SetMethod;
ParameterExpression paramo = Expression.Parameter(typeof(object), "param");
ParameterExpression parami = Expression.Parameter(typeof(TProp), "newvalue");
MethodCallExpression methodCallSetterOfProperty =
Expression.Call(Expression.Convert(paramo, type), setterMethodInfo, parami);
var setPropertyValueExp =
Expression.Lambda<Action<object, TProp>>(methodCallSetterOfProperty, paramo, parami);
var setterFunc = setPropertyValueExp.Compile();
return setterFunc;
}