为什么动态关键字不能用于动态加载的程序集?

lon*_*ero 14 c# dynamic-keyword dynamic-assemblies

我正在研究一个CSharp表达式求值程序,可以使用,如下所示.该组件生成代码并在内存中编译它,之后,它加载生成的程序集,创建生成的类的实例并运行它.结果保存在字典中.

我的问题是所有运行正常,直到最后一行代码失败,异常:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException'object '不包含'FirstName'的定义.

但是,Visual Studio能够向我展示专业变量内容:

Professional = { FirstName = Juan Pablo, 
                LastName = Ibañez, 
                Certifications = <>f__AnonymousType0`3[System.String,System.String,System.String][], 
                SayHi = System.Action }
Run Code Online (Sandbox Code Playgroud)

这是代码:

    static void Main(string[] args)
    {
        const string data = @"results[""professional""] = 
        new
        {
            FirstName = ""Juan Pablo"",
            LastName = ""Ibañez"",
            Certifications = new[]
            {
                new { Provider=""MSFT"", ExamCode = ""70-536"", Title = ""TS: Microsoft .NET Framework – Application Development Foundation"" },
                new { Provider=""MSFT"", ExamCode = ""70-505"", Title = ""TS: Microsoft .NET Framework – Application Development Foundation"" },
                new { Provider=""MSFT"", ExamCode = ""70-563"", Title = ""TS: Microsoft .NET Framework – Application Development Foundation"" }
            },

            SayHi = new System.Action(()=> System.Console.WriteLine(""Hi""))
        };";

        var eval = CSharpEvaluator.Evaluate(data); // return a disctionary<string, object>
        dynamic professional = eval["professional"];
        Console.WriteLine("First Name: {0}", professional.FirstName);
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

谢谢.

Jon*_*eet 27

编辑:我想我已经知道了.匿名类型是内部类型,因此类型对于dynamic活页夹是不可见的.立即验证......

是的,就是这样.请注意确切的错误消息:'object' does not contain a definition for 'FirstName'".

它正在使用,object因为这是你可以从你自己的程序集中实际引用对象的唯一类型.这与动态加载的程序集无关 - 它只是在一个不同的程序集中.

编辑:你可以使用该[InternalsVisibleTo]属性绕过这个,如果你可以让你的"发布"程序集应用它.这是一个例子:

// In Library.dll
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("Test")]

public class Library
{
    public static object Foo()
    {
        return new { ID = 1 };
    }
}

// In Test.exe
using System;

class Test
{
    static void Main()
    {
        dynamic d = Library.Foo();
        Console.WriteLine(d.ID);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您注释掉该属性,Test.exe会根据您的问题中断.使用该属性,它工作正常.C#编译器的作者想到了一切:)

  • c#编译器团队中的人永远不会让我惊讶. (4认同)