为什么在内部类中C#找不到动态的接口方法?

问题描述

我尝试使用dynamic访问位于另一个程序集中的类的方法。这些类是internal,由返回public接口的构建器创建。由于某些原因,dynamic无法调用接口上定义的方法。我可以使用“经典”反射来使代码运行,但是我不明白为什么它不能与dynamic一起使用。

我知道dynamic不能使用内部类的方法,但是这里我们有一个公共接口。因此,请问有人可以解释为什么在下面的示例中dynamic抛出RuntimeBinderException吗?

    namespace SandBoxLib  // located in SandBoxLib.dll
    {
        public class InternalBuilder
        {
            public static IInterface Build()
            {
                return new InternalClass();
            }
        }

        public interface IInterface
        {
            void IfMethod();
        }
        
        internal class InternalClass : IInterface
        {
            public void IfMethod() { }
        }
    }

    namespace SandBox  // located in SandBox.dll
    {
        public class Program
        {
            static void Main(string[] args)
            {
                var inst = InternalBuilder.Build();
                dynamic dynInst = inst;

                inst.IfMethod();     // ok
                dynInst.IfMethod();  // Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a deFinition for 'IfMethod'
            }
        }
    }

解决方法

此行为在C#标准中进行了描述:

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#dynamic-binding

在“成员查找”下显示:

成员查找不仅考虑成员的名称,还考虑成员的名称。 成员拥有的类型参数的数量以及成员是否为 可访问

由于找到了IfMethod()分辨率的成员dynamicinternal,所以根据规范,呼叫将失败。