Ответ 1
Вам нужно использовать ExpandoObject
dynamic o = new ExpandoObject();
o.Title = "Ghostbusters";
o.Rating = "PG";
Console.WriteLine(m.PrintMovie(o));
Я получаю сообщение об ошибке:
"объект" не содержит определения для "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' **
хотя он находится в динамическом объекте.
Вот скриншот:
Я делаю что-то вроде этого и пытаюсь вызвать функцию фильма из тестового проекта.
Вам нужно использовать ExpandoObject
dynamic o = new ExpandoObject();
o.Title = "Ghostbusters";
o.Rating = "PG";
Console.WriteLine(m.PrintMovie(o));
Ответ Jahamal не говорит, почему вы получаете ошибку. Причина в том, что анонимный класс internal
для сборки. Ключевое слово dynamic
не позволяет обойти видимость элемента.
Решение заключается в замене анонимного класса на именованный открытый класс.
Вот еще один хороший пример, объясняющий причину и другое возможное решение.
Причина, по которой вызов
data2.Person
завершается сбой, заключается в том, что информация о типеdata2
недоступна во время выполнения. Причина, по которой она недоступна, заключается в том, что анонимные типы не являются общедоступными. Когда метод возвращает экземпляр этого анонимного типа, он возвращаетSystem.Objec
t, который ссылается на экземпляр анонимного типа - тип, информация которого недоступна основной программе. Динамическое время выполнения пытается найти свойство, называемоеPerson
для объекта, но не может устранить его из информации о типе, которую он имеет. Таким образом, он выдает исключение. Вызовdata.Name
отлично работает, посколькуPerson
является общедоступным классом, эта информация доступна и может быть легко разрешена.Это может повлиять на вас в любом из следующих случаев (если не больше):
- Вы возвращаете непубличный не-внутренний тип, используя
System.Object
.- Вы возвращаете непубличный неинтерминированный производный тип через общедоступный базовый тип и получаете доступ к свойству в производном типе, который не относится к базовому типу.
- Вы возвращаете что-либо, завернутое в анонимный тип из другой сборки.
В моем случае у меня был проект 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
{
...
Ссылки:
В моем случае у меня есть тестовый проект xUnit.
Где 'content' - это строка json.
Этот код выдает ошибку:
dynamic parsed = JsonConvert.DeserializeObject<dynamic>(content);
Этот код работает. Используйте ExpandoObject вместо динамического, например:
dynamic parsed = JsonConvert.DeserializeObject<ExpandoObject>(content);