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?
Vâng, đây là cách tôi đã triển khai nó trong CSharpEval – EnderWiggin