Почему динамическое ключевое слово не работает с динамически загруженными сборками?
Я работаю над оценщиком выражения CSharp, который можно использовать, как вы можете видеть ниже. Этот компонент генерирует код и компилирует его в памяти, и после этого он загружает сгенерированную сборку, создает экземпляр сгенерированного класса и запускает его. Результаты сохраняются в словаре.
Моя проблема в том, что все запускают ok до последней строки кода, где она не выполняется с исключением:
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
EDIT: Я думаю, что у меня это есть. Анонимные типы являются внутренними, поэтому тип не отображается для связывания dynamic
. Проверка теперь...
Да, это так. Обратите внимание на точные сообщения об ошибке: 'object' does not contain a definition for 'FirstName'".
Он использует object
, потому что это единственный тип, который вы могли бы действительно ссылаться на объект как из вашей собственной сборки. Это не связано с тем, что сборка загружается динамически - это просто вопрос о том, что она находится в другой сборке.
EDIT: вы можете обойти это, используя атрибут [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 разбивается по вашему вопросу. С атрибутом он отлично работает. Авторы компилятора С# думают обо всем:)