2012-07-26 7 views
5

Sto lavorando con il codice che istanzia dinamicamente l'oggetto SoapHttpClientProtocol (classe proxy) e utilizza questo oggetto per effettuare una chiamata al servizio Web WS-Basic I. Ecco la versione semplificata del mio codice:Utilizzare l'espressione Lambda compilata anziché Activator.CreateInstance per inizializzare l'oggetto SoapHttpClientProtocol

public override object Call(Type callingObject, 
string method, object[] methodParams, string URL) 
{ 
    MethodInfo requestMethod = callingObject.GetMethod(method); 

    //creates an instance of SoapHttpClientProtocol 
    object instance = Activator.CreateInstance(callingObject); 

    //sets the URL for the object that was just created 
    instance.GetType().InvokeMember("Url", 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null, 
    instance, 
    new object[1] {URL}); 

    return requestMethod.Invoke(instance, methodParams); 
} 

Ho notato che in alcuni casi Activator.CreateInstance() chiamata può assumere notevole quantità di tempo, quindi sto cercando di ottimizzare il codice by using a lambda expression:

public override object Call(Type callingObject, 
string method, object[] methodParams, string URL) 
{ 
    MethodInfo requestMethod = callingObject.GetMethod(method); 

    //creates an instance of SoapHttpClientProtocol using compiled Lambda Expression 
    ConstructorInfo constructorInfo = callingObject.GetConstructor(new Type[0]); 
    object instance = Expression.Lambda(Expression.New(constructorInfo)).Compile(); 

    //sets the URL for the object that was just created 
    instance.GetType().InvokeMember("Url", 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty, null, 
    instance, 
    new object[1] {URL}); 

    //calls the web service 
    return requestMethod.Invoke(instance, methodParams); 
} 

Sfortunatamente, questo codice non crea un oggetto del tipo callingObject (invece restituisce un oggetto delegato Func<T>) e quindi quando tenta di impostare lo Url nella riga successiva genera un'eccezione:

System.MissingMethodException: Tentativo di accedere a un membro mancante.

Mi manca qualcosa nel mio codice?

Grazie!

+0

Link è morto a proposito – NStuke

risposta

3

La parte Expression.Lambda(Expression.New(constructorInfo)).Compile() restituisce un delegato Func<T> che avvolge un costruttore di Type memorizzato nel parametro callingObject. Per realtà chiamata che costruttore, è ancora necessario per invocarlo:

Delegate delegateWithConstructor = Expression.Lambda(Expression.New(constructorInfo)).Compile(); 
object instance = delegateWithConstructor.DynamicInvoke(); 

Tuttavia, ciò che si sta cercando di fare sembra abbastanza strana e fragile nel lungo periodo, dal momento che si sta passando in giro i nomi dei metodi, come semplici stringhe e parametri come oggetti, perdendo quindi tutti i tipi di controllo in fase di compilazione. Perché hai bisogno di farlo?

+0

+1, breve e semplice. Ma perché riprendere "Delegare" e fare invocazione dinamica? Perché non solo 'Func' e poi()? – nawfal

0

L'utilizzo di alberi di espressione farà rallentare l'esecuzione del programma a meno che non venga memorizzata nella cache un'espressione compilata.

Problemi correlati