dynamic은 프로젝트 참조의 속성에 대한 정의를 포함하지 않습니다.


93

다음과 같은 오류가 발생합니다.

'개체'에 '제목'에 대한 정의가 없습니다.

모든 코드는 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);
    }
} 

동일한 프로젝트에서 잘 작동하지만 ConsoleApplication1에 대한 참조로 ConsoleApplication2를 추가하고 정확히 동일한 코드를 추가하면

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));
        }
    }
}

오류가 발생합니다.

'객체'에 '제목'에 대한 정의가 없습니다 **

동적 개체에 있더라도.

  • o.Title 'o.Title'에서 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException'유형의 예외가 발생했습니다. dynamic {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

다음은 스크린 샷입니다. 여기에 이미지 설명 입력

나는 이와 같은 일을하고 테스트 프로젝트에서 영화 함수를 호출하려고합니다.


답변:


79

ExpandoObject를 사용해야합니다.

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

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

28
그는, 그가 로버트 알 수 있듯이 그는 오류를 얻고 이유를 알려이 좋을 것이다 정교한 질문을 작성하는 문제를 많이 겪었
루이스 Ferrao

2
expando 개체와 함께 인라인 이니셜 라이저 기능을 사용할 수없는 것 같습니까?
Roberto Bonini 2015 년

1
ExpandoObject는 어디에 사용해야합니까? 동적 개체를 만들거나 동적 개체를 구문 분석하기 위해?
Hosein Aqajani

Robert의 답변이 도움이 되었기 때문에 더 많은 정보를 검색해야했지만 더 깊은 이해가 필요했습니다. Oreilly 여기에 동적 유형에 대한 좋은 기사가 있었다 : oreilly.com/learning/building-c-objects-dynamically
빌리 러비에게

139

Jahamal의 대답은 오류가 발생하는 이유 를 말하지 않습니다 . 그 이유는 익명 클래스가 internal어셈블리에 있기 때문입니다 . 키워드로 dynamic회원 가시성을 우회 할 수 없습니다.

해결책은 익명 클래스를 명명 된 공용 클래스로 바꾸는 것입니다.

그 이유와 다른 가능한 해결책을 설명하는 또 다른 좋은 예가 있습니다 .

에 대한 호출이 data2.Person실패 하는 이유는 의 유형 정보 data2를 런타임에 사용할 수 없기 때문입니다. 사용할 수없는 이유는 익명 유형이 공개되지 않기 때문입니다. 메서드가 해당 익명 유형의 인스턴스를 반환 할 때 익명 유형 System.Objec의 인스턴스를 참조하는 t를 반환합니다 . 즉, 주 프로그램에서 정보를 사용할 수없는 유형입니다. 동적 런타임 Person은 개체에 대해 호출 된 속성을 찾으려고 하지만 개체에있는 유형 정보에서 확인할 수 없습니다. 따라서 예외가 발생합니다. 호출에 data.Name있기 때문에 작품을 잘 Personpublic 클래스가이 정보를 사용할 수 있습니다 쉽게 해결할 수 있습니다.

이는 다음과 같은 경우에 영향을 미칠 수 있습니다 (그 이상은 아닐 경우).

  1. .NET을 사용하여 비공개, 비 내부 유형을 반환합니다 System.Object. 2. 공개 기본 유형을 통해 비공개, 내부가 아닌 파생 유형을 반환하고 기본 유형에없는 파생 유형의 속성에 액세스합니다. 3. 다른 어셈블리에서 익명 형식으로 래핑 된 항목을 반환합니다.

1
답변에 출처를 인용 해 주시겠습니까?
d3dave

@ d3dave 대답의 두 가지 주장을 테스트 할 수 있습니다. .NET 디 컴파일러에서 클래스 가시성을 확인할 수 있습니다. 에 대한 액세스 규칙 dynamic은 다양한 가시성을 가진 멤버가있는 테스트 클래스에서 확인할 수 있습니다.
Robert Važan

3
이것이 OP가하는 일이 왜 문제인지에 대한 진정한 대답입니다.
Matti Virkkunen

1
netcoreapp1.1 인 소스와 테스트 프로젝트간에이 작업을 수행 할 수 없습니다. 내 잘못인지 아니면 .NET Core에서 작동하지 않는지 알 수 있습니까?
Anthony Mastrean

29

제 경우에는 Visual Studio에서 만든 단위 테스트 프로젝트가 있었고 데이터 계층 라이브러리에서 메서드를 테스트해야하는 많은 경우가있었습니다. 모두 변경하고 싶지 않았으므로 다음을 사용하여 테스트 어셈블리를 친구로 표시했습니다.

[assembly:InternalsVisibleTo("MyDataLayerAssemblyName")]

그리고 그것은 그것을 해결했습니다.

예:

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

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

   [TestClass]
   public class ContactTests
   {
      ...

참조 :


1
그 이유는 Alexander Stepaniuk가 말한 것입니다. 귀하의 의견이 해결책입니다. 감사!
Pato Loco

netcoreapp1.1 프로젝트간에이 작업을 수행 할 수 없으며 잘못하고있는 것인지 확실하지 않습니다.
Anthony Mastrean

대단히 감사합니다 Jelgab! 이제 동적을 ExpanoObject로 바꿀 필요가 없습니다! 내 단위 테스트에서 종속성 주입을 사용하고 있는데 동적을 사용할 수 없으며 단위 테스트 프로젝트에서 작동하도록 할 수 없습니다. 그러나 이것은 그것을 해결했습니다!
ShameWare

개발자 (개발자)는 익명 유형이 생성되는 반대 프로젝트에 추가해야합니다.이 경우에는 둘 다 추가해야합니다.
ryanwebjackson

0

제 경우에는 xUnit 테스트 프로젝트가 있습니다.

여기서 'content'는 json 문자열 입니다.

이 코드는 오류를 발생시킵니다.

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

이 코드는 작동합니다. 다음 과 같이 동적으로 구성된 ExpandoObject를 사용하십시오 .

dynamic parsed = JsonConvert.DeserializeObject<ExpandoObject>(content);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.