динамический не содержит определения свойства из ссылки на проект - PullRequest
78 голосов
/ 23 февраля 2012

Я получаю сообщение об ошибке:

«объект» не содержит определения для «Заголовок»

весь код также на github

У меня есть ConsoleApplication1, который выглядит следующим образом

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Movie m = new Movie();
            var o = new { Title = "Ghostbusters", Rating = "PG" };
            Console.WriteLine(m.PrintMovie(o));
        }
    }
} 

и Movie.cs

public class Movie : DynamicObject
{
    public string PrintMovie(dynamic o)
    {
        return string.Format("Title={0} Rating={1}", o.Title, o.Rating);
    }
} 

он отлично работает из того же проекта, но если я добавлю ConsoleApplication2 со ссылкой на ConsoleApplication1 и добавлю точно такой же код

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            Movie m = new Movie();
            var o = new { Title = "Ghostbusters", Rating = "PG" };
            Console.WriteLine(m.PrintMovie(o));
        }
    }
}

Я получаю ошибку:

'object' не содержит определения для 'Title' **

даже если он находится в динамическом объекте.

  • o.Title 'o.Title' вызвал исключение типа 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' dynamic {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

Вот снимок экрана: enter image description here

Я делаю что-то подобное и пытаюсь вызвать функцию фильма из тестового проекта.

Ответы [ 3 ]

118 голосов
/ 20 марта 2014

Ответ Джахамала не говорит , почему вы получаете ошибку.Причина в том, что анонимный класс internal для сборки.Ключевое слово dynamic не позволяет вам игнорировать видимость участника.

Решение состоит в том, чтобы заменить анонимный класс именованным открытым классом.

Вот еще один хороший пример, объясняющий причину, и другое возможное решение .

Причина сбоя вызова data2.Person заключается в том, что информация о типе data2 недоступна во время выполнения.Причина, по которой он недоступен, в том, что анонимные типы не являются публичными.Когда метод возвращает экземпляр этого анонимного типа, он возвращает System.Objec t, который ссылается на экземпляр анонимного типа - тип, информация которого недоступна основной программе.Динамическая среда выполнения пытается найти свойство с именем Person в объекте, но не может разрешить его из информации о типе, которая у него есть.Таким образом, он создает исключение.Вызов data.Name работает нормально, поскольку Person является общедоступным классом, эта информация доступна и может быть легко решена.

Это может повлиять на вас в любом из следующих случаев (если не больше):

  1. Вы возвращаете непубличный, не внутренний тип, используя System.Object.
  2. Вы возвращаете непубличный, не внутренний производный тип через открытый базовый тип и получаете доступ к свойству в производном типе, которого нет в базовом типе.
  3. Вы возвращаете все, что находится внутри анонимного типа, из другой сборки.
73 голосов
/ 23 февраля 2012

Вам необходимо использовать ExpandoObject

 dynamic o = new ExpandoObject();
 o.Title = "Ghostbusters";
 o.Rating = "PG";

 Console.WriteLine(m.PrintMovie(o));
23 голосов
/ 16 апреля 2015

В моем случае у меня был проект Unit Test, который я создал в Visual Studio, и во многих случаях мне нужно было тестировать методы в библиотеке уровня данных.Я не хотел менять их все, поэтому пометил тестовую сборку как друга с помощью:

[assembly: InternalsVisibleTo ("MyDataLayerAssemblyName")]

И это решило ее.

Пример:

using System.Runtime.CompilerServices;
using Microsoft.VisualStudio.TestTools.UnitTesting;

[assembly: InternalsVisibleTo( "MyDataLayerAssembly" )]
namespace MyUnitTestProject.DataTests
{

   [TestClass]
   public class ContactTests
   {
      ...

Ссылки: Класс InternalsVisibleToAttribute

Сборки друзей

...