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

发布于 2024-10-18 13:14:55 字数 1631 浏览 0 评论 0原文

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

我的问题是一切都运行正常,直到最后一行代码失败并出现异常:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException“对象”不包含“FirstName”的定义。

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

Professional = { FirstName = Juan Pablo, 
                LastName = Ibañez, 
                Certifications = <>f__AnonymousType0`3[System.String,System.String,System.String][], 
                SayHi = System.Action }

这是代码:

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

有什么想法吗?

谢谢。

I'm working on a CSharp expression evaluator which can be used as you can see below. This component generates code and compiles it in memory and after that, it loads the generated assembly, creates an instance of the generated class and run it. Results are saved in a dictionary.

My problem is that all run ok until the last line of code where it fails with the exception:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException 'object' does not contain a definition for 'FirstName'.

However, Visual Studio is able to show me the professional variable content:

Professional = { FirstName = Juan Pablo, 
                LastName = Ibañez, 
                Certifications = <>f__AnonymousType0`3[System.String,System.String,System.String][], 
                SayHi = System.Action }

And this is the code:

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

Any ideas?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

紧拥背影 2024-10-25 13:14:55

编辑:我想我已经明白了。匿名类型是内部类型,因此该类型对于动态绑定器不可见。现在正在验证...

是的,就是这样。请注意确切的错误消息:'object' 不包含 'FirstName'" 的定义。

它使用 object 因为这是您实际上可以使用的唯一类型 em> 从您自己的程序集中引用该对象。这与动态加载的程序集无关 - 这只是它位于不同程序集中的问题

:您可以绕过。使用 [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);
    }
}

如果您注释掉该属性,则 Test.exe 将根据您的问题进行中断。 ,它工作得很好。C# 编译器作者考虑了一切:)

EDIT: I think I've got it. Anonymous types are internal, so the type isn't visible to the dynamic binder. Verifying now...

Yup, that's it. Note the exact error message: 'object' does not contain a definition for 'FirstName'".

It's using object because that's the only type you could actually refer to the object as from within your own assembly. This has nothing to do with the assembly being loaded dynamically - it's simply a matter of it being in a different assembly.

EDIT: You can get round this using the [InternalsVisibleTo] attribute, if you can make your "publishing" assembly apply that. Here's an example:

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

If you comment out the attribute, Test.exe breaks as per your question. With the attribute, it works fine. The C# compiler authors think of everything :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文