简体   繁体   English

从继承的接口调用Method时传递动态参数会引发RuntimeBinderException

[英]Passing a dynamic parameter throws RuntimeBinderException when calling Method from Inherited interface

Ran into an interesting runtime issue after some refactoring and have pinned in down to the following situation. 经过一些重构后遇到了一个有趣的运行时问题,并锁定了以下情况。

When passing a property from a dynamic object to a method on an Interface that has been inherited from a parent interface the runtime binder cannot find the method. 将属性从动态对象传递到接口上从父接口继承的方法时,运行时绑定程序找不到该方法。

Here is a test to demonstrate both failure and success (when calling method directly on the parent interface type) 这是一个演示失败和成功的测试(当直接在父接口类型上调用方法时)

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);
        }
    }
}

Test #1 Fails: Assert.AreEqual failed. 测试#1失败:Assert.AreEqual失败。 Expected:<(null)>. 预期值:<(null)>。 Actual:. 实际:。 'Test.Utility.IInheritEcho' does not contain a definition for 'EchoString' 'Test.Utility.IInheritEcho'不包含'EchoString'的定义

Test #2 Succeeds. 测试#2成功。

My question is whether my assumption that the 1st test should pass is correct or is there a fundamental reason in the framework that it does not? 我的问题是我对第一个测试应该通过的假设是正确的还是在框架中是否有一个根本原因不通过?

I know I can fix the issue by casting the parameters when I pass them in or assigning them to variables before passing them in. I'm more just curious as to the reason the inherited interface is causing the RuntimeBinder to fail... 我知道我可以通过在传递参数时将其强制转换或在传递参数之前将其分配给变量来解决此问题。我只是好奇继承的接口导致RuntimeBinder失败的原因...

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

A good question this. 这是一个很好的问题。

It would appear that it's taking the type of the expression at compile time, IInheritEcho , and not deep-searching the members of inherited interfaces when looking for the method to invoke dynamically. 在寻找动态调用的方法时, IInheritEcho在编译时采用表达式的类型IInheritEcho ,而不是深度搜索继承接口的成员。

And ideally the C# runtime binder for a dynamic expression should behave the same way as the C# compiler - therefore it should see that the IEcho interface is inherited by IInheritEcho and it should work. 理想情况下, dynamic表达式的C#运行时绑定程序的行为应与C#编译器的行为相同-因此,它应该看到IEcho接口是由IInheritEcho继承的并且应该可以工作。

We can test the hypothesis - ie that it's the static typing - by doing this in the first test: 我们可以通过在第一个测试中进行以下操作来检验假设(即它是静态类型):

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

Hey presto - the test passes. 嘿,谢谢-测试通过了。

So the issue is not that the dynamic binder can't find the method - it's that when the instance whose member is being invoked dynamically is statically typed as an interface, inherited interfaces are not consulted. 因此,问题不在于动态绑定程序找不到方法-而是当动态动态调用其成员的实例被静态类型化为接口时,不会查询继承的接口。

In my opinion this behaviour is incorrect. 我认为这种行为是不正确的。

Please Eric Lippert... be nice... 请埃里克·利珀特...好...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将int []传递给参数类型为动态的方法时发生RunTimeBinderException - RunTimeBinderException when passing int[] to method having parameter type dynamic 将C#动态与COM对象一起使用会引发RuntimeBinderException,以记录已实现接口的方法 - Using C# dynamic with COM object throws RuntimeBinderException for documented method of implemented interface 事件回调<dynamic>抛出 RuntimeBinderException</dynamic> - EventCallback<dynamic> throws RuntimeBinderException 为什么在调用方法时使用带动态的json.net获取RuntimeBinderException - Why do I get a RuntimeBinderException using json.net with dynamic when calling a method 带有动态对象的RuntimeBinderException调用公共静态方法TryParse - RuntimeBinderException with dynamic object calling public static method TryParse ASP.NET MVC-将动态ExpandoObject从控制器传递到视图时出现RuntimeBinderException - ASP.NET MVC - RuntimeBinderException when passing dynamic ExpandoObject from Controller to View 动态属性分配引发RuntimeBinderException - Dynamic Property Assignment Throws RuntimeBinderException 动态转换为ObjectHandle会引发RuntimeBinderException - Casting dynamic to ObjectHandle throws RuntimeBinderException 从不同库中方法的“ dynamic”结果读取属性时出现RuntimeBinderException - RuntimeBinderException when reading property from `dynamic` result from method in different library 为什么“((dynamic)dictionary).MyKey”抛出RuntimeBinderException? - Why “((dynamic) dictionary).MyKey” throws a RuntimeBinderException?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM