2011-10-19 25 views
10

Tôi đang viết proxy trang trí bằng cách sử dụng Castle DynamicProxy. Tôi cần đánh chặn của proxy để chặn chỉ sở hữu viết (không đọc) vì vậy tôi đang kiểm tra tên của phương pháp thusly:Xác định xem thể hiện MethodInfo có phải là trình truy cập thuộc tính

public void Intercept(IInvocation invocation) 
{ 
    if (invocation.Method.Name.StartsWith("set_") 
    { 
     // ... 
    } 

    invocation.Proceed(); 
} 

Bây giờ này hoạt động tốt nhưng tôi không thích thực tế proxy của tôi có kiến ​​thức sâu sắc về cách các thuộc tính được triển khai: Tôi muốn thay thế kiểm tra tên phương thức bằng một cái gì đó tương tự như:

if (invocation.Method.IsPropertySetAccessor) 

Thật không may là Google-fu của tôi đã thất bại. Bất kỳ ý tưởng?

Trả lời

15

Bạn có thể kiểm tra xem một tài sản tồn tại mà phương pháp này là setter (chưa được kiểm tra): (. Cảm hứng lấy từ Marc's answer to a related question)

bool isSetAccessor = invocation.Method.DeclaringType.GetProperties() 
     .Any(prop => prop.GetSetMethod() == invocation.Method) 

+1

Trông rất bất tiện – thepirat000

+0

@ thepirat000: Vâng, nếu 'GetSetMethod' là O (1), đây sẽ là O (n). Đó có lẽ không phải là tối ưu (và tôi chắc chắn sẽ upvote bất kỳ câu trả lời thay thế mà là có thể đọc được và mang lại hiệu suất tốt hơn), nhưng tôi chắc rằng bạn biết câu nói về tối ưu hóa sớm là gốc rễ của tất cả các điều ... – Heinzi

+0

Tôi sẽ đề nghị bạn để kiểm tra xem phương thức có tiền tố "get_" (không phân biệt) và loại bỏ nó khỏi bộ sưu tập phương thức (còn O (n) phức tạp - mà là khá rẻ). Ngoài ra, bạn có thể thêm thể hiện 'Dictionary ' để giữ các kiểu đã được kiểm tra trước tiên cho bạn độ phức tạp của O (n) nhưng sau đó O (1) –

-4

Tôi nghĩ bạn có thể thử sử dụng phương pháp khuyến nông: http://msdn.microsoft.com/en-us/library/bb383977.aspx

+0

Cảm ơn, nhưng đây là cách giải pháp hiện tại của tôi hoạt động. Tôi đang tìm một trong đó không yêu cầu ứng dụng của tôi để biết về chi tiết thực hiện trình biên dịch C#. –

+0

Anh ta có thể sử dụng một phương thức mở rộng để thêm phương thức 'IsPropertySetAccessor' vào kiểu' MethodInfo', nhưng vấn đề anh ta có là phương thức đó sẽ tốt hơn so với phương thức mà anh ta có bây giờ. ** "Tôi không thích thực tế proxy của tôi có kiến ​​thức thân mật về cách thức các thuộc tính được thực hiện" ** –

+2

Câu trả lời này là khá vô ích - câu hỏi dường như chỉ nhiều hơn vào "cái gì sẽ đi * bên trong * một phương pháp để xác định điều này " –

5

Không có bất kỳ voodoo trong đó Tôi biết. Bạn có thể, có thể, hãy bỏ một số tài sản có tên đó, và so sánh ví dụ MethodInfo (invocation.Method) với người truy cập thuộc tính (GetSetMethod()) - tuy nhiên, tôi không thể thành thật nói (mà không kiểm tra) nhận được cùng một ví dụ MethodInfo (ngay cả khi nó cùng một phương pháp).

if(method.IsSpecialName && method.Name.StartsWith("set_")) 
{ 
    var prop = typeof (Foo).GetProperty(method.Name.Substring(4), 
      BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 
    var accessor = prop.GetSetMethod(); 
    bool isSame = accessor == method; 
} 
-1

Trước tiên, bạn có thể kiểm tra tài sản của MemberTypeMethodInfo lớp để xem nếu nó là một Property.

Bây giờ, bạn nên thử đoán xem đó là bộ sưu tập hay tập hợp. Nếu bạn không muốn phân tích tên (ai đó có thể đặt tên cho một phương thức "set_Something"), thì bạn có thể kiểm tra các đối số.

  • Nếu accessor sở hữu chấp nhận một tham số và trả về void, nó là một tập hợp
  • Nếu accessor tài sản trả về một giá trị và không chọn các thông số, nó là một có được

Bạn chỉ có thể quan tâm đến lần kiểm tra đầu tiên

+2

Chỉ cần yêu cầu của sự tò mò. Còn toán tử [] này thì sao? Tôi nghĩ nó cho phép một tham số. – dowhilefor

+0

'MemberType' của phương thức truy cập thuộc tính là' MemberTypes.Method' không phải 'MemberTypes.Property'. Dù sao cũng cảm ơn bạn. –

+0

@dowhilefor: điểm tốt !!! Bạn có thể thấy trong Reflector/ILDASM kết quả và cho chúng tôi biết không? Tôi không có cả Reflector và một assembly với một accessor này, nhưng mscorlib.dll nên đầy trong số chúng –

0

từ đối tượng MethodInfo của bạn nhận được MemberType thuộc tính nên cho biết đây là Property type do đó bạn có thể truyền nó thành PropertyInfo thay thế. đối tượng đó phơi bày thuộc tính CanWrite cho biết đây có phải là setter hay không.

+0

Hmm, tài liệu dường như ngụ ý rằng 'MemberType' sẽ là' MemberTypes.Method' cho 'MethodInfo' các đối tượng. –

+0

hmm, bạn đã đúng, tôi đã bỏ qua điều này và mong đợi nó là MemberTypes.Property cho các đối tượng MethodInfo được tạo cho các thuộc tính, có thể là tôi không chắc nữa bây giờ – mtijn

+0

Tôi vừa chạy thử nghiệm: 'MemberType' của một phương thức accessor thuộc tính là 'MemberTypes.Method' không phải' MemberTypes.Property' để nó không bay. Cảm ơn dù sao đi nữa. –

3

Tôi không chắc chắn những loại loại các invocation.Method là, nhưng nếu bạn có thể lấy PropertyInfo, bạn có thể sử dụng IsSpecialName. Thật không may, điều này không chỉ cho biết thuộc tính là một set_ hoặc _get mà còn nếu nó là toán tử quá tải.

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