使用Compiled Lambda表达式而不是Activator.CreateInstance来初始化SoapHttpC

本文关键字:CreateInstance Activator 初始化 SoapHttpC Compiled Lambda 表达式 使用 | 更新日期: 2024-07-27 19:12:05

我正在处理动态实例化SoapHttpClientProtocol对象(代理类)并使用此对象调用WS-Basic I Web Service的代码。这是我的代码的简化版本:

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); 
}

我注意到,在某些情况下,Activator.CreateInstance()调用可能会花费大量时间,因此我试图通过使用lambda表达式来优化代码:

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); 
}

不幸的是,这段代码并没有创建callingObject类型的对象(相反,它返回了一个Func<T>委托对象),因此当它试图在下一行设置Url时,它会抛出一个异常:

System.MissingMethodException:试图访问丢失的成员。

我的代码中遗漏了什么吗?

谢谢!

使用Compiled Lambda表达式而不是Activator.CreateInstance来初始化SoapHttpC

Expression.Lambda(Expression.New(constructorInfo)).Compile()部分返回一个Func<T>委托,该委托封装了存储在callingObject参数中的Type的构造函数。要真正调用该构造函数,您仍然需要调用它:

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

然而,从长远来看,您试图做的事情似乎很奇怪,也很脆弱,因为您将方法名作为简单的字符串传递,将参数作为对象传递,因此会丢失所有的编译时类型检查。你为什么要这么做?

除非缓存已编译的表达式,否则使用表达式树会导致程序运行速度减慢。