2011-01-19 42 views
14

Tôi đang gặp một số vấn đề với cách gọi phương thức tĩnh quá tải với tham số ngoài thông qua phản xạ và sẽ đánh giá cao một số con trỏ.Phản ánh trên phương pháp quá tải tĩnh sử dụng tham số ngoài

Tôi đang tìm cách tạo động kiểu như System.Int32 hoặc System.Decimal và sau đó gọi phương thức tĩnh TryParse(string, out x) trên đó.

Mã dưới đây có hai vấn đề:

  • t.GetMethod("TryParse", new Type[] { typeof(string), t }) thất bại trong việc trả lại MethodInfo Tôi hy vọng

  • mi.Invoke(null, new object[] { value.ToString(), concreteInstance }) dường như thành công nhưng không thiết lập ra param concreteInstance với giá trị phân tích cú pháp

Được đan xen vào chức năng này, bạn có thể thấy một số mã tạm thời thể hiện những gì nên hap bút nếu tham số type được đặt thành System.Decimal.

public static object Cast(object value, string type) 
{ 
    Type t = Type.GetType(type); 
    if (t != null) 
    { 
     object concreteInstance = Activator.CreateInstance(t); 
     decimal tempInstance = 0; 

     List<MethodInfo> l = new List<MethodInfo>(t.GetMethods(BindingFlags.Static | BindingFlags.Public)); 

     MethodInfo mi; 
     mi = t.GetMethod("TryParse", new Type[] { typeof(string), t }); //this FAILS to get the method, returns null 
     mi = l.FirstOrDefault(x => x.Name == "TryParse" && x.GetParameters().Length == 2); //ugly hack required because the previous line failed 
     if (mi != null) 
     { 
      try 
      { 
       bool retVal = decimal.TryParse(value.ToString(), out tempInstance); 
       Console.WriteLine(retVal.ToString());  //retVal is true, tempInstance is correctly set 
       object z = mi.Invoke(null, new object[] { value.ToString(), concreteInstance }); 
       Console.WriteLine(z.ToString());   //z is true, but concreteInstance is NOT set 
      } 
      catch (Exception ex) 
      { 
       Debug.WriteLine(ex.Message); 
      } 
     } 

     return concreteInstance; 
    } 

    return value; 
} 

Tôi cần phải làm gì để đảm bảo rằng cuộc gọi t.GetMethod() của tôi trả về đúng MethodInfo? Tôi cần phải làm gì để có số concreteInstance được đặt chính xác trong cuộc gọi mi.Invoke() của mình?

Tôi biết có một loạt câu hỏi về chủ đề này, nhưng hầu hết trong số chúng liên quan đến phương pháp chung chung tĩnh hoặc phương pháp tĩnh không bị quá tải. This question tương tự nhưng không trùng lặp.

Trả lời

26

Bạn cần sử dụng đúng BindingFlags và sử dụng Type.MakeByRefType cho các thông số outref. Một giây, và tôi sẽ có một mẫu mã cho bạn.

Ví dụ,

MethodInfo methodInfo = typeof(int).GetMethod(
    "TryParse", 
    BindingFlags.Public | BindingFlags.Static, 
    Type.DefaultBinder, 
    new[] { typeof(string), typeof(int).MakeByRefType() }, 
    null 
); 

Tôi phải chỉ ra rằng cách gọi này là một chút khó khăn quá. Đây là cách bạn làm điều đó.

string s = "123"; 
var inputParameters = new object[] { "123", null }; 
methodInfo.Invoke(null, inputParameters); 
Console.WriteLine((int)inputParameters[1]); 

Các null đầu tiên là vì chúng ta đang gọi một phương thức tĩnh (không có đối tượng "nhận" gọi này). null trong inputParameters sẽ được "lấp đầy" cho chúng tôi bằng TryParse với kết quả của phân tích cú pháp (đó là thông số out).

+0

Câu trả lời hay, cảm ơn @ Jason. – slugster

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