gpt4 book ai didi

dynamic - 如何将 void 方法调用表示为 DynamicMetaObject.BindInvokeMember 的结果?

转载 作者:行者123 更新时间:2023-12-03 05:50:28 25 4
gpt4 key购买 nike

我试图举一个简短的例子 IDynamicMetaObjectProvider对于第二版 C# 深入研究,我遇到了问题。

我希望能够表达一个 void 调用,但我失败了。我确信这是可能的,因为如果我使用反射绑定(bind)器动态调用 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
}
}

这会引发异常:

Unhandled Exception: System.InvalidCastException: The result type 'System.Void' of the dynamic binding produced by the object with type 'DynamicDemo' for the binder 'Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder' is not compatible with the result type 'System.Object' expected by the call site.

如果我将方法更改为返回对象并返回 null,它可以正常工作...但我不希望结果为 null,我希望它为 void。这对于反射绑定(bind)器来说效果很好(请参阅 Main 中的第一个调用),但对于我的动态对象来说却失败了。我希望它像反射绑定(bind)器一样工作 - 调用该方法就可以,只要您不尝试使用结果即可。

我是否错过了可以用作目标的特定表达方式?

最佳答案

这类似于:

DLR return type

您确实需要匹配 ReturnType 属性指定的返回类型。对于所有标准二进制文件,这几乎被固定为对象或无效(对于删除操作)。如果您知道自己正在进行无效调用,我建议将其包装在:

Expression.Block(
call,
Expression.Default(typeof(object))
);

DLR 过去对于允许的内容相当宽松,并且会自动提供一些最少量的强制。我们放弃了它,因为我们不想提供一组对每种语言可能有意义或没有意义的约定。

听起来你想阻止:

dynamic x = obj.SomeMember();

没有办法做到这一点,总会返回一个值,用户可以尝试继续动态交互。

关于dynamic - 如何将 void 方法调用表示为 DynamicMetaObject.BindInvokeMember 的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1835912/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com