2012-02-23 18 views
59

Dostaję błąd, który mówi:dynamiczny nie zawiera definicji nieruchomości z odniesieniem projektu

'object' does not contain a definition for 'Title'

cały kod jest również na github

Mam ConsoleApplication1, który wygląda tak

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

i Movie.cs

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

współpracuje z projektu samo, ale jeśli dodać ConsoleApplication2 z odniesieniem do ConsoleApplication1 i dodać dokładnie ten sam kod

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

pojawia się błąd:

'object' does not contain a definition for 'Title'**

chociaż znajduje się w dynamicznym obiekcie.

  • o.Title 'o.Title' zwrócił wyjątek typu 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' dynamiczne {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

Oto zrzut ekranu: enter image description here

Robię coś takiego i próbuję wywołać funkcję filmu z projektu testowego.

+1

możliwe duplikat [C# 'dynamiczne' nie mają dostępu do właściwości z anonimowych typów zgłoszonych w innym zespole] (http: // Stackoverflow .pl/questions/2630370/c-sharp-dynamic-can-access-properties-from-anonymous-types-declaration-in-anot) –

Odpowiedz

61

Musisz użyć ExpandoObject

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

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

Zrobił wiele trudu, aby napisać skomplikowane que Chciałbym dać mu znać, dlaczego dostał błąd, jak sugeruje Robert –

+0

. Czy nie wydaje ci się, że możesz użyć wbudowanej funkcji inicjalizacyjnej z obiektem expando? –

+0

Znakomita, działa również z testowaniem jednostek. –

90

odpowiedź Jahamal nie mówi dlaczego pojawi się błąd. Powodem jest to, że anonimowa klasa to internal do złożenia. Słowo kluczowe dynamic nie pozwala na ominięcie widoczności członków.

Rozwiązaniem jest zastąpienie anonimowej klasy nazwaną klasą publiczną.

Oto kolejny dobry przykład wyjaśniający przyczynę i another possible solution.

The reason the call to data2.Person fails is that the type information of data2 is not available at runtime. The reason it's not available is because anonymous types are not public. When the method is returning an instance of that anonymous type, it's returning a System.Objec t which references an instance of an anonymous type - a type who's info isn't available to the main program. The dynamic runtime tries to find a property called Person on the object, but can't resolve it from the type information it has. As such, it throws an exception. The call to data.Name works fine since Person is a public class, that information is available and can be easily resolved.

This can affect you in any of the following cases (if not more):

  1. You're returning a non-public, non-internal type using System.Object .
  2. You're returning a non-public, non-internal derived type via a public base type and accessing a property in the derived type that's not in the base type.
  3. You're returning anything wrapped inside an anonymous type from a different assembly.
+0

Czy możesz podać swoje źródło w odpowiedzi? – d3dave

+0

@ d3dave Dwa twierdzenia w odpowiedzi można przetestować. Widoczność klasy można sprawdzić w dekompilatorze .NET. Reguły dostępu dla 'dynamic' można sprawdzić w klasie testowej z członkami o różnej widoczności. –

+1

To jest prawdziwa odpowiedź na pytanie, dlaczego działanie OP było problemem. –

15

W moim przypadku miałem jednostkę projekt testowy, że utworzony w Visual Studio i wiele przypadków, gdzie potrzebne do testowania metod na bibliotekę warstwy danych. Nie chciałem, aby zmienić wszystkie z nich oznaczony więc zespół testowy jako przyjaciela za pomocą:

[montaż: InternalsVisibleTo („MyDataLayerAssemblyName”)]

I rozwiązać go.

przykład:

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

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

    [TestClass] 
    public class ContactTests 
    { 
     ... 

Odniesienia: InternalsVisibleToAttribute Class

Friend Assemblies

+1

Powodem jest to, co powiedział Alexander Stepaniuk. Twój komentarz jest rozwiązaniem. Dzięki! –

+0

Nie mogę uruchomić tego między projektami netcoreapp1.1, nie jestem pewien, czy to coś, co robię nieprawidłowo. –

Powiązane problemy