2009-02-06 28 views
23

Tôi thực hiện phân tích kiểu nào đó trong thời gian chạy bằng Phản chiếu. Nếu tôi có một cá thể MethodInfo, làm thế nào tôi có thể tìm ra nếu đây là phương pháp "thực" hoặc là phương thức getter/setter của một thuộc tính? Và nếu nó là một tài sản, làm thế nào tôi có thể tìm thấy nó lưu trữ PropertyInfo trở lại?Tìm tài sản lưu trữ PropertyInfo từ MethodInfo của getter/setter

Trả lời

7

Ecma 335 chỉ định (nhưng không yêu cầu) trình biên dịch sử dụng tiền tố get_/set_ (chương 22.28). Tôi không biết bất kỳ ngôn ngữ nào phá vỡ đề xuất đó. Làm cho nó dễ dàng:

public static PropertyInfo GetPropFromMethod(Type t, MethodInfo method) { 
    if (!method.IsSpecialName) return null; 
    return t.GetProperty(method.Name.Substring(4), 
    BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); 
} 
+2

Từ văn bản thông tin, nó được yêu cầu phải tuân thủ CLS, nhưng không bắt buộc phải là hợp lệ IL. –

+1

Tôi sẽ không khuyên bạn nên đi theo cách này. Tôi khuyên bạn nên kiểm tra tất cả các thuộc tính. Quy ước mẫu chuỗi - không mạnh mẽ. –

+1

Tôi rất muốn xem một ví dụ phản đối. –

17

Vâng, phương pháp đằng sau phương thức getter và setter "thực".

Theo dõi lại thuộc tính - mẫu (return vs take 1 arg) sẽ giúp thu hẹp nó - nhưng bạn sẽ phải gọi GetGetMethod/GetSetMethod trên mỗi để tìm thuộc tính.

Bạn có thể có thể thử số Name (ít nhận __/set__) - nhưng cảm thấy dễ vỡ. Đây là phiên bản dài hơn (không sử dụng số Name):

static PropertyInfo GetProperty(MethodInfo method) 
{ 
    bool takesArg = method.GetParameters().Length == 1; 
    bool hasReturn = method.ReturnType != typeof(void); 
    if (takesArg == hasReturn) return null; 
    if (takesArg) 
    { 
     return method.DeclaringType.GetProperties() 
      .Where(prop => prop.GetSetMethod() == method).FirstOrDefault(); 
    } 
    else 
    { 
     return method.DeclaringType.GetProperties() 
      .Where(prop => prop.GetGetMethod() == method).FirstOrDefault(); 
    } 
} 
+0

+1 cho giải pháp thay thế, vẫn thích 'name.StartsWith ("get_"/"set_")'. – arul

+0

hmm ... có thể cho mã C#, ít nhất ... chúng được đề cập trong 17.2.7.1 của ECMA 335 - nhưng điều này có được áp dụng cho các ngôn ngữ khác không? Tôi sẽ kiểm tra ECMA 334 ... –

+0

Chắc chắn là, hãy kiểm tra phần 17.2.7.1. Đối với thuộc tính P thuộc loại T, các chữ ký sau đây được đặt trước: T get_P(); void set_P (giá trị T); Cả hai chữ ký đều được bảo lưu, ngay cả khi thuộc tính chỉ đọc hoặc chỉ ghi. – arul

5

Nhìn vào MethodBase.IsSpecialName. Các phương thức không được hiển thị rõ ràng, chẳng hạn như các trình truy cập thuộc tính, các phương thức đăng ký sự kiện và các toán tử quá tải sử dụng cờ này.

Theo hiểu biết của tôi, không có cách nào để tìm số PropertyInfo mà không cần lặp qua các thuộc tính và so sánh các phương pháp.

+0

Theo MS, bạn không thể đảm bảo rằng cờ IsSpecialName sẽ được đặt: http://connect.microsoft.com/VisualStudio/feedback/details/108302/for-property-accessors-get-set-isspecialname-false –

+0

IsSpecialName dường như không hoạt động. Tôi hy vọng đây là một cái gì đó MS thay đổi bởi vì nó tốt hơn để có thể kiểm tra lá cờ hơn là phải lý do những gì các tính năng ngôn ngữ được thực hiện như (có thể không đánh dấu) phương pháp đặc biệt. –

5

Tôi thực sự muốn rời khỏi đây như một lời nhận xét, nhưng tôi không thể kể từ khi đại diện của tôi isnt đủ cao :(

Theres một lỗi trong mã Marc Gravell của: nếu nó một indexer nó sẽ trả về null, ngay cả khi một tài sản cha mẹ tồn tại của nó tốt đẹp để có mà nhanh chóng thất bại, nhưng tôi nghĩ rằng chúng tôi chỉ có thể làm như vậy khi nó có phải là một giá trị trả về hoặc một tham số:.

[Pure] 
    public static PropertyInfo GetParentProperty(this MethodInfo method) 
    { 
     if (method == null) throw new ArgumentNullException("method"); 
     var takesArg = method.GetParameters().Length == 1; 
     var hasReturn = method.ReturnType != typeof(void); 
     if (!(takesArg || hasReturn)) return null; 

     if (takesArg && !hasReturn) 
     { 
      return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetSetMethod() == method); 
     } 
     else 
     { 
      return method.DeclaringType.GetProperties().FirstOrDefault(prop => prop.GetGetMethod() == method); 
     } 
    } 
-1

Bí quyết để chơi với là BindingFlags.DeclaredOnlyIsSpecialName

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