开发者

Why doesn't dynamic keyword work with dynamically loaded assemblies?

开发者 https://www.devze.com 2023-02-12 04:00 出处:网络
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 a

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 { Pro开发者_如何转开发vider=""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.


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

0

精彩评论

暂无评论...
验证码 换一张
取 消