Подтвердить что ты не робот

Динамическое не содержит определения свойства из ссылки на проект

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

"объект" не содержит определения для "Title"

весь код также находится на 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);
    }
} 

он отлично работает в проекте SAME, но если я добавлю 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

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

4b9b3361

Ответ 1

Вам нужно использовать ExpandoObject

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

 Console.WriteLine(m.PrintMovie(o));

Ответ 2

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

Решение заключается в замене анонимного класса на именованный открытый класс.

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

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

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

  • Вы возвращаете непубличный не-внутренний тип, используя System.Object.
  • Вы возвращаете непубличный неинтерминированный производный тип через общедоступный базовый тип и получаете доступ к свойству в производном типе, который не относится к базовому типу.
  • Вы возвращаете что-либо, завернутое в анонимный тип из другой сборки.

Ответ 3

В моем случае у меня был проект 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
   {
      ...

Ссылки:

Ответ 4

В моем случае у меня есть тестовый проект xUnit.

Где 'content' - это строка json.

Этот код выдает ошибку:

dynamic parsed = JsonConvert.DeserializeObject<dynamic>(content);

Этот код работает. Используйте ExpandoObject вместо динамического, например:

dynamic parsed = JsonConvert.DeserializeObject<ExpandoObject>(content);