我正在尝试为《C#深度探索》第二版提供一个短小的示例,展示 IDynamicMetaObjectProvider
的用法,但遇到了问题。
我想要表达一个 void 调用,但一直失败。我确信这是可能的,因为如果我使用反射绑定器动态调用 void 方法,一切正常。以下是一个简短但完整的示例:
using System;
using System.Dynamic;
using System.Linq.Expressions;
class DynamicDemo : IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression expression)
{
return new MetaDemo(expression, this);
}
public void TestMethod(string name)
{
Console.WriteLine(name);
}
}
class MetaDemo : DynamicMetaObject
{
internal MetaDemo(Expression expression, DynamicDemo demo)
: base(expression, BindingRestrictions.Empty, demo)
{
}
public override DynamicMetaObject BindInvokeMember
(InvokeMemberBinder binder, DynamicMetaObject[] args)
{
Expression self = this.Expression;
Expression target = Expression.Call
(Expression.Convert(self, typeof(DynamicDemo)),
typeof(DynamicDemo).GetMethod("TestMethod"),
Expression.Constant(binder.Name));
var restrictions = BindingRestrictions.GetTypeRestriction
(self, typeof(DynamicDemo));
return new DynamicMetaObject(target, restrictions);
}
}
class Test
{
public void Foo()
{
}
static void Main()
{
dynamic x = new Test();
x.Foo(); // Works fine!
x = new DynamicDemo();
x.Foo(); // Throws
}
}
下面的代码会抛出一个异常:
未处理的异常: System.InvalidCastException: 动态绑定对象 'DynamicDemo' 由绑定程序 'Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder' 生成的类型 'System.Void' 的结果类型与调用位置期望的类型 'System.Object' 不兼容。
如果我把方法改成返回object类型并返回null,那么它就能正常工作...但是我不想让结果为空,我想让它是void。这对于反射绑定器来说没有问题(参见Main中的第一个调用),但对于我的动态对象来说却失败了。我希望它能像反射绑定器一样工作——只要不尝试使用结果,调用该方法就可以了。
我是否错过了可以用作目标的特定表达式?