2014-04-19 13 views
5

Tôi cần tạo một System.Linq.Expressions.Expression gọi là đối tượng động. Đối tượng động có thể là ExpandoObject hoặc bất kỳ đối tượng nào khác IDynamicMetaObjectProvider.Cách đúng để xây dựng Biểu thức .NET để gọi các đối tượng động

Hãy xem xét các thử nghiệm sau đây:

var myInstance = DateTime.Now; 

var methodInfo = myInstance.GetType().GetMethod("ToUniversalTime"); 

var methodCallExpression = Expression.Call(Expression.Constant(myInstance), methodInfo); 
var expression = Expression.Lambda(methodCallExpression); 

Assert.AreEqual(myInstance.ToUniversalTime(), expression.Compile().DynamicInvoke()); 

tôi cần phải tạo ra một biểu thức tương đương khi myInstance được khai báo tương tự (chỉ là một ví dụ):

dynamic myInstance = new ExpandoObject(); 
myInstance.MyMethod = new Func<string>(() => "hello world"); 

Tôi cho rằng tôi cần phải sử dụng Expression.Dynamic phương pháp (xem MSDN). Nhưng tôi không biết cách sử dụng nó. Tôi đã cố gắng để tìm kiếm trên google nhưng các ví dụ duy nhất mà tôi đã tìm thấy sử dụng lớp Microsoft.CSharp.RuntimeBinder.Binder (xem MSDN) mà không thể được chính thức sử dụng:

API này hỗ trợ các cơ sở hạ tầng .NET Framework và không có ý định sẽ được sử dụng trực tiếp từ mã của bạn.

Sử dụng Microsoft.CSharp.RuntimeBinder.Binder tôi có thể viết mã bên dưới:

dynamic myInstance = new ExpandoObject(); 
myInstance.MyMethod = new Func<string>(() => "hello world"); 

var binder = Binder.InvokeMember(
    CSharpBinderFlags.None, 
    "MyMethod", 
    null, 
    this.GetType(), 
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) }); 

var methodCallExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(myInstance)); 
var expression = Expression.Lambda(methodCallExpression); 

Assert.AreEqual(myInstance.MyMethod(), expression.Compile().DynamicInvoke()); 

Nó giải pháp này có đúng không?

+1

Vâng, đây là cách tôi đã triển khai nó trong CSharpEval – EnderWiggin

Trả lời

-1
dynamic x = typeof("<<MethodName>>") 
      .GetMethod("ToUniversalTime") 
      .Invoke(<<Type Of Object>>, new object[] { [Parameter1,]      
      [Parameter2,....] }); 

trong mã này "Loại" thay vì từ đó loại đối tượng bạn phải gọi phương thức ...

ghi rõ tên phương pháp của bạn thay vì "methodname"

và cuối cùng đối tượng của bạn thay vì "Loại Object"

và nếu không có tham số sau đó vượt qua mảng trống rỗng ... khác khôn ngoan vượt qua thay vì "parameter1,2, và vân vân.

+1

Tôi đang tìm cách xây dựng một cây biểu thức, xem lớp Biểu thức. Mã của bạn chỉ đơn giản gọi một methid thông qua sự phản ánh. –

1

đây là con mèo ch: từ sự hiểu biết của tôi, không có ý nghĩa trong việc thực hiện một cuộc gọi năng động mà không có một số loại đối tượng Binder.

Đối tượng binder đại diện cho các quy tắc được tuân thủ để phân giải tên động:

  • trận đấu nên được trường hợp nhạy cảm?
  • Phương thức quá tải nên được giải quyết như thế nào?
  • Phải làm gì nếu đối tượng là đối tượng không động?
  • Bạn sử dụng những hạn chế nào?

Nói cách khác, đối tượng Binder đại diện cho ngữ nghĩa của "ngôn ngữ" gọi, trong khi IDynamicMetaObjectProvider đại diện cho ngữ nghĩa của đối tượng được gọi.

Vì vậy, có, chúng tôi không được phép sử dụng đối tượng Binder CSharp. Điều đó có thể được cảm thấy đặc biệt là khi một số vấn đề xảy ra mà chỉ có thể được làm việc xung quanh bằng cách sử dụng nội bộ của đối tượng. Tuy nhiên, giải pháp thay thế chỉ đơn giản là sử dụng một triển khai khác, không được cung cấp khung, thực hiện Binder.

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