C# 转换为接口类型时未调用DynamicObject.TryConvert
下面的代码引发一个异常。未调用TryConvert以转换到接口。为什么会这样?我能解决这个问题吗C# 转换为接口类型时未调用DynamicObject.TryConvert,c#,dynamic,C#,Dynamic,下面的代码引发一个异常。未调用TryConvert以转换到接口。为什么会这样?我能解决这个问题吗 using System.Dynamic; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { dynamic test = new JsonNull(); var ok = (string)
using System.Dynamic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
dynamic test = new JsonNull();
var ok = (string)test;
// Next line throws:
// Unable to cast object of type 'ConsoleApplication1.JsonNull' to type 'ConsoleApplication1.IFoo'.
var fail = (IFoo)test;
}
}
class JsonNull : DynamicObject
{
public override bool TryConvert(ConvertBinder binder, out object result)
{
result = null;
return !binder.Type.IsValueType;
}
}
interface IFoo { }
}
我怀疑这是因为在C#(可能还有.NET一般情况下)中,您无法创建到接口类型的用户定义转换(就像您无法创建到基/子类型的用户定义转换一样)。因此,每个接口转换都被视为框或引用转换 不过这只是一个猜测 编辑:另一方面,我刚刚查看了为以下内容生成的代码:
dynamic d = ...;
IDisposable x = (IDisposable) d;
它确实通过
Binder.Convert
生成了一个动态调用,所以这不是C#编译器做的。嗯。我发现如果你改变这一行:
var fail = (IFoo)test;
为此:
IFoo success = test;
它按预期工作
在这种情况下,似乎只有隐式转换起作用。在我看来像个虫子
我还发现这也失败了,这非常令人恼火:
class Program {
static void Main(string[] args) {
dynamic test = new JsonNull();
Fails(test);
}
static void Fails(IFoo ifoo) { }
}
// ...
因为它看起来也应该使用隐式转换。另一个bug?Chris Burrows在博客中解释了这种行为: “当调用站点的底层语言为任何操作提供一些绑定时,DynamicObject(..)中还有另一个障碍,该绑定会否决可能存在的任何动态绑定 (..)回想一下,在C#(6.2.4,bullet 3)中,从大多数类类型到任何接口类型都有显式转换,尽管它们可能会失败。(..) 仅对接口转换示例进行一点扩展,它特别奇怪,因为如果转换是隐式的(比如,尝试分配给本地),那么动态转换就会工作。为什么?因为C#binder会说,“不!没有隐式转换到IEnumerable,”然后DynamicObject实现将让TryConvert完成它的任务。”
文件上怎么说?这是否得到支持?你有没有找到一种方法来解决这个问题?这也是我的直觉。我假设对接口进行强制转换并不意味着返回不同的对象实例,只是返回同一实例的不同视图。@Andrew:您可能想自己尝试实现
IDynamicMetaObjectProvider
。我不知道它是否达到了这样的程度。它还适用于返回值:IEnumerable SomeFunc(){dynamic x=…;return x;}
在我的动态对象上调用TryConvert