Почему динамическое ключевое слово не работает с динамически загружаемыми сборками? - PullRequest
13 голосов
/ 21 февраля 2011

Я работаю над оценщиком выражений 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);

Есть идеи?

Спасибо.

1 Ответ

27 голосов
/ 21 февраля 2011

РЕДАКТИРОВАТЬ: Я думаю, что у меня есть. Анонимные типы являются внутренними, поэтому тип не отображается для подшивки 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);
    }
}

Если вы закомментируете атрибут, Test.exe прекратит работу в соответствии с вашим вопросом. С атрибутом все работает нормально. Авторы компилятора C # думают обо всем:)

...