Converti Func espressione a Func dove T è un vincolo generico

c# expression-trees generics typeconverter

Domanda

Ho questa funzione statica

public static object Create(Type t)
{
    //unimportant
}

Non ho il controllo sulla funzione sopra riportata sopra, quindi non posso alterarlo. Il problema è che non è generico, quindi devo eseguire il cast dell'oggetto restituito ad un certo tipo. Questo tipo è fornito dal vincolo di un'altra classe generica da cui chiamo il metodo Create .

Questo è dove ho raggiunto:

public static class Creator<T>
{
    public static void Create()
    {
        var m = typeof(SomeClass).GetMethod("Create");
        var p = Expression.Parameter(typeof(Type));
        var e = Expression.Call(m, p);

        //at this stage I want to create delegate for calling the 'Create' method, 
        //then pass typeof(T) as parameter, get returned object, 
        //and finally cast it to 'T'.

        //for eg, I can do it like this:
        var f = Expression.Lambda<Func<Type, object>>(e, p).Compile();
        Func<T> mainThing = () => (T)f(typeof(T));

        //is there a way I can achieve in one step?
    }
}

Nel mio approccio sopra non sto compilando il delegato finale ma un passaggio in precedenza. Come faccio a incorporare il cast anche prima della compilazione e restituire Func<T> ?

Risposta accettata

Penso che tu abbia solo bisogno di una chiamata a Expression.Convert e di usare Expression.Convert ConstantExpression anziché Expression.Convert ParameterExpression :

var method = typeof(SomeClass).GetMethod("Create");
var call = Expression.Call(method, Expression.Constant(typeof(T), typeof(Type)));
var conversion = Expression.Convert(call, typeof(T));
var function = Expression.Lambda<Func<T>>(conversion).Compile();

(Non l'ho provato, ma sembra ok ...)


Risposta popolare

Sembra che tu stia saltando attraverso un sacco di cerchi inutili. Non capisco perché lo stai facendo attraverso un albero delle espressioni. Perché non solo:

public static class Creator<T>
{
    public static void Create()
    {
        Func<T> mainThing = () => (T)SomeClass.Create(typeof(T));
    }
}

???

Qual è lo scopo di creare un albero di espressioni di una chiamata di metodo solo per trasformarlo in un delegato che effettua una chiamata al metodo che poi chiama? Perché non chiamare semplicemente SomeClass.Create direttamente?

C'è qualcosa che mi manca qui?

Per rispondere alla tua domanda attuale:

Come faccio a incorporare il cast anche prima della compilazione?

Utilizzare Expression.Convert() per creare un nodo di albero di espressioni che rappresenta una conversione.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché