2012-07-26 39 views
5

Tôi đang làm việc với mã tự động khởi tạo đối tượng SoapHttpClientProtocol (lớp proxy) và sử dụng đối tượng này để thực hiện cuộc gọi đến WS-Basic I Web Service. Dưới đây là phiên bản đơn giản hóa của mã của tôi:Sử dụng biểu thức Lambda biên dịch thay vì Activator.CreateInstance để khởi tạo đối tượng 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); 
} 

tôi đã nhận thấy rằng trong một số trường hợp Activator.CreateInstance() cuộc gọi có thể mất nhiều thời gian, vì vậy tôi đang cố gắng để tối ưu hóa mã 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); 
} 

Thật không may, mã này không tạo đối tượng thuộc loại callingObject (thay vào đó nó trả về đối tượng đại diện Func<T>) và do đó khi cố gắng đặt Url trong dòng tiếp theo, nó sẽ ngoại lệ:

System.MissingMethodException: Đã cố gắng truy cập một thành viên bị thiếu.

Tôi có thiếu thứ gì đó trong mã của mình không?

Cảm ơn!

+0

Liên kết bị chết theo cách – NStuke

Trả lời

3

Phần Expression.Lambda(Expression.New(constructorInfo)).Compile() trả về một Func<T> đại biểu kết thúc tốt đẹp một hàm tạo Type được lưu trữ trong thông số callingObject. Để thực sự gọi constructor đó, bạn vẫn cần phải gọi nó:

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

Tuy nhiên, những gì bạn đang cố gắng làm có vẻ khá lạ và mong manh trong thời gian dài, kể từ khi bạn đang đi xung quanh tên phương pháp như chuỗi đơn giản và các tham số như các đối tượng, do đó mất tất cả các loại kiểm tra thời gian biên dịch. Tại sao bạn cần phải làm điều đó?

+0

+1, ngắn và đơn giản. Nhưng tại sao lại đưa 'Delegate' trở lại và thực hiện lệnh gọi động? Tại sao không chỉ 'Func' và sau đó()? – nawfal

0

Sử dụng cây biểu thức sẽ làm cho chương trình của bạn chạy chậm hơn trừ khi bạn lưu biểu thức được lưu vào bộ nhớ cache.

Các vấn đề liên quan