2012-07-26 11 views
5

Estoy trabajando con el código que instancia dinámicamente el objeto SoapHttpClientProtocol (clase proxy) y utiliza este objeto para realizar una llamada al servicio web WS-Basic I. Esta es la versión simplificada de mi código:Usar expresión Lambda compilada en lugar de Activator.CreateInstance para inicializar el objeto 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); 
} 

me he dado cuenta que en algunos casos puede tomar la llamada Activator.CreateInstance() cantidad significativa de tiempo, por lo que estoy tratando de optimizar el código 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); 
} 

por desgracia, este código no crea un objeto del tipo callingObject (en lugar devuelve un objeto delegado Func<T>) y por lo tanto cuando se trata de establecer el Url en la siguiente línea lanza una excepción:

System.MissingMethodException: Intentó acceder a un miembro faltante.

¿Falta algo en mi código?

Gracias!

+0

El enlace está muerto por cierto – NStuke

Respuesta

3

La parte Expression.Lambda(Expression.New(constructorInfo)).Compile() devuelve un delegado Func<T> que envuelve un constructor de Type almacenada en callingObject parámetro. Para realmente llamada ese constructor, que todavía tienen que invocar:

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

Sin embargo, lo que está tratando de hacer parece bastante extraño y frágil en el largo plazo, dado que está pasando alrededor de los nombres de métodos como cadenas simples y parámetros como objetos, perdiendo así toda la verificación de tipos en tiempo de compilación. ¿Por qué necesitas hacerlo?

+0

+1, corto y simple. ¿Pero por qué tomar 'Delegate' y hacer invocación dinámica? ¿Por qué no solo 'Func' y luego()? – nawfal

0

El uso de árboles de expresiones hará que el programa se ejecute más lento a menos que almacene en caché la expresión compilada.

Cuestiones relacionadas