Ho un metodo che viene utilizzato per generare una NewExpression
.
public NewExpression CreateNewExpression( Expression<Func<T>> expression )
{
return expression.Body as NewExpression;
}
Puoi quindi fare cose come questa.
CreateNewExpression( () => new MyType() );
Successivamente viene utilizzato per creare un delegato che può essere eseguito per creare un oggetto.
var body = Expression.MemberInit( constructorExpression, bindings );
var funcType = typeof( Func<> ).MakeGenericType( objectType );
var lambda = Expression.Lambda( funcType, body ).Compile();
Funziona alla grande, ma ora vorrei passare alcuni dati nel metodo in modo che possa essere utilizzato nella costruzione dell'oggetto.
public NewExpression CreateNewExpression( Expression<Func<T, Data>> expression )
Questo sarebbe quindi usato in questo modo.
CreateNewExpression( data => new MyType( data.Id ) );
Non posso per la vita di me capire come creare l'espressione corretta per passare i dati per il costruttore da utilizzare.
Se non estraggo il corpo dall'espressione in CreateNewExpression ed eseguo Expression.Invoke
, non so come impostare le proprietà su di esso dopo.
Se estraggo il corpo, posso impostare le proprietà usando Expression.MemberInit
, ma non riesco a capire come passare i dati ad esso.
Come posso fare questo?
Quando si desidera utilizzare un'espressione che contiene ParameterExpression
, è necessario riutilizzare anche la stessa ParameterExpression
nell'espressione finale.
Per fare ciò, è possibile accedere ai Parameters
dell'espressione originale e quindi passare il parametro a Expression.Lambda()
. Il risultato potrebbe essere simile a questo:
public Delegate M<T>(Expression<Func<Data, T>> expression)
{
var objectType = typeof(T);
var constructorExpression = (NewExpression)expression.Body;
var constructorParameterExpression = expression.Parameters.Single();
var bindings = …;
var body = Expression.MemberInit( constructorExpression, bindings );
var funcType = typeof( Func<,> ).MakeGenericType( typeof(Data), objectType );
var lambda = Expression.Lambda( funcType, body, constructorParameterExpression )
.Compile();
return lambda;
}
Penso che quella che potrebbe essere la risposta al tuo problema è Expression.Parameter
.
Ho trovato un post sul blog su geek con blog che utilizza questo. L'unico lato negativo di questa soluzione è che dovresti creare nuovi overload per quando hai bisogno di più di tre argomenti. Ma immagino che questo possa essere facilmente risolto con l' params object[]
.