传递动态参数会在从继承的接口调用方法时引发运行时绑定器异常

本文关键字:方法 运行时 异常 绑定 调用 接口 参数 动态 继承 | 更新日期: 2023-09-27 18:33:48

经过一些重构后遇到了一个有趣的运行时问题,并已确定为以下情况。

将属性从动态对象传递到从父接口继承的接口上的方法时,运行时绑定程序找不到该方法。

下面是一个测试,用于演示失败和成功(直接在父接口类型上调用方法时(

using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test.Utility
{
    public interface IEcho
    {
        string EchoString(string input);
    }
    public interface IInheritEcho : IEcho
    { }
    public class EchoClass : IInheritEcho
    {
        public string EchoString(string input)
        {
            return input;
        }
    }
    [TestClass]
    public class RuntimeBinderTest
    {
        [TestMethod]
        public void RuntimeBinder_should_work_when_dynamic_parameters_are_passed_to_method_from_inherited_interface()
        {
            //Arrange
            dynamic dynObject = new ExpandoObject();
            dynObject.Foo = "Bar";
            IInheritEcho echomore = new EchoClass();
            string echo = null;
            string exceptionMessage = null;
            //Act
            try
            {
                echo = echomore.EchoString(dynObject.Foo);
            }
            catch (RuntimeBinderException e)
            {
                exceptionMessage = e.Message;
            }
            //Assert
            Assert.AreEqual(echo, dynObject.Foo, false, exceptionMessage);
        }
        [TestMethod]
        public void RuntimeBinder_should_work_when_dynamic_parameters_are_passed_to_method_from_noninherited_interface()
        {
            //Arrange
            dynamic dynObject = new ExpandoObject();
            dynObject.Foo = "Bar";
            IEcho echomore = new EchoClass();
            string echo = null;
            string exceptionMessage = null;
            //Act
            try
            {
                echo = echomore.EchoString(dynObject.Foo);
            }
            catch (RuntimeBinderException e)
            {
                exceptionMessage = e.Message;
            }
            //Assert
            Assert.AreEqual(echo, dynObject.Foo, false, exceptionMessage);
        }
    }
}

测试 #1 失败:Assert.AreEqual失败了。预期:<(空(>。实际:。"Test.Utility.IInheritEcho"不包含"EchoString"的定义

测试 #2 成功。

我的问题是,我对第一次测试应该通过的假设是否正确,还是框架中存在它没有通过的根本原因?

我知道我可以通过在传入参数时转换参数或在传入之前将它们分配给变量来解决此问题。我只是好奇继承的接口导致运行时绑定器失败的原因......

传递动态参数会在从继承的接口调用方法时引发运行时绑定器异常

您的情况是Microsoft Connect 上记录的错误

是一个很好的问题。

看起来它在编译时采用表达式的类型,IInheritEcho,而不是在查找要动态调用的方法时深入搜索继承接口的成员。

理想情况下,dynamic表达式的 C# 运行时绑定器的行为方式应与 C# 编译器相同 - 因此它应该看到IEcho接口由IInheritEcho继承,并且它应该可以工作。

我们可以通过在第一个测试中这样做来测试假设 - 即它是静态类型 - :

echo = ((dynamic)echomore).EchoString(dynObject.Foo);

嘿普雷斯托 - 测试通过。

因此,问题不在于动态绑定程序找不到该方法 - 而是当动态调用其成员的实例静态类型化为接口时,不会引用继承的接口。

在我看来,这种行为是不正确的。

请埃里克·利珀特... 做个好人...