2008-09-21 27 views
5

Tôi cần phải viết một hàm nhận thuộc tính làm tham số và thực thi trình lấy nó.Làm cách nào để chuyển thuộc tính chung thành tham số cho hàm?

Nếu tôi cần phải vượt qua một chức năng/đại biểu tôi đã sử dụng:

delegate RET FunctionDelegate<T, RET>(T t); 

void func<T, RET>(FunctionDelegate function, T param, ...) 
{ 
    ... 
    return function.Invoke(param); 
} 

Có cách nào tương tự để xác định một tài sản để tôi có thể gọi đó là phương thức getter và/hoặc setter trong các mã chức năng?

Trả lời

7

Bạn có thể sử dụng sự phản chiếu, bạn có thể nhận được một đối tượng MethodInfo cho người truy cập get/set và gọi đó là phương thức Gọi.

Các mã ví dụ giả định bạn có cả một get và thiết accessors và bạn thực sự cần phải thêm xử lý lỗi nếu bạn muốn sử dụng điều này trong mã sản xuất:

Ví dụ để có được giá trị của tài sản Foo đối tượng obj bạn có thể viết:

value = obj.GetType().GetProperty("Foo").GetAccessors()[0].Invoke(obj,null); 

để cài đặt nó:..

obj.GetType().GetProperty("Foo").GetAccessors()[1].Invoke(obj,new object[]{value}); 

Vì vậy, bạn có thể vượt qua obj.GetType() GetProperty ("Foo") GetAccessors() [0] để phương pháp của bạn và thực thi phương thức Invoke của nó.

một cách dễ dàng hơn là sử dụng phương pháp vô danh (điều này sẽ làm việc trong .net 2.0 hoặc mới hơn), hãy sử dụng một phiên bản sửa đổi một chút ví dụ mã của bạn:

delegate RET FunctionDelegate<T, RET>(T t); 

void func<T, RET>(FunctionDelegate<T,RET> function, T param, ...) 
{ 
    ... 
    return function(param); 
} 

cho một tài sản mang tên Foo kiểu int đó là một phần của một SomeClass lớp:

SomeClass obj = new SomeClass(); 
func<SomeClass,int>(delegate(SomeClass o){return o.Foo;},obj); 
3

Thuộc tính đơn giản là cú pháp đường cho phương pháp.

Tôi không nghĩ rằng bạn có thể sửa đổi thuộc tính sao cho nó trở thành một thực thể "có người gọi bạn có thể gọi".

Tuy nhiên, bạn có thể tạo phương thức GetPropertyValue() và chuyển nó xung quanh như thể đó là đại biểu.

+1

Đó là một ý tưởng rất tốt dọc theo nguyên tắc KISS. Thật không may tại thời điểm này tôi không thể sử dụng nó :( Vấn đề là tài sản tôi đang sử dụng không phải là một phần của mã của tôi Và viết một wrapper thêm chi phí tôi không muốn tại thời điểm này –

2

@Dror Helper,

Tôi e rằng bạn không thể làm theo cách đó. Trình biên dịch tạo ra các phương thức get_PropertyName và set_PropertyName nhưng chúng không thể truy cập được nếu không sử dụng Reflection. IMO tốt nhất bạn có thể làm là tạo chức năng mất System.Reflection.ProperyInfoSystem.Object thông số và trả về propInfo.GetValue (obj, null);

1

Re: aku của câu trả lời:

Sau đó, bạn có để có được những thông tin bất động sản đầu tiên. Có vẻ như "sử dụng sự phản chiếu" là câu trả lời tiêu chuẩn cho các câu hỏi C# khó hơn, nhưng sự phản chiếu tạo ra mã không khó để duy trì. Dror, tại sao không chỉ tạo ra một đại biểu mà đọc tài sản cho bạn? Đó là một lớp lót đơn giản và có lẽ là giải pháp nhanh nhất và đẹp nhất cho vấn đề của bạn.

+0

Yep, giải pháp sẽ liên quan đến Reflection anyway Bạn có thể tạo một số trình bao bọc hữu ích, nhưng tôi thích có mã đơn giản hơn. Thực hành cho thấy các giải pháp phản chiếu phức tạp rất dễ vỡ – aku

+1

Martijn - Tôi đã trả lời bạn về việc tạo một trình bao bọc - mặc dù nó là một giải pháp đơn giản, nó không phải là thứ tôi cần –

11

Bạn cũng có thể viết một cái gì đó như:

static void Method<T, U>(this T obj, Expression<Func<T, U>> property) 
     { 
      var memberExpression = property.Body as MemberExpression; 
      //getter 
      U code = (U)obj.GetType().GetProperty(memberExpression.Member.Name).GetValue(obj, null); 
      //setter 
      obj.GetType().GetProperty(memberExpression.Member.Name).SetValue(obj, code, null); 
     } 

và ví dụ về gọi:

DbComputerSet cs = new DbComputerSet(); 
cs.Method<DbComputerSet, string>(set => set.Code); 
+0

Ngoài ra còn có khả năng xảy ra UnaryExpression mà bạn phải tính đến. Hãy xem tại đây: http://stackoverflow.com/a/2916344/265877 – Alex

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