2012-02-23 25 views
59

Recibo un error que dice:dinámica no contiene una definición de una propiedad de una referencia de proyecto

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

todo el código está también en github

Tengo un ConsoleApplication1 que tiene este aspecto

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

y Movie.cs

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

funciona bien desde el mismo proyecto, pero si añado ConsoleApplication2 con una referencia a ConsoleApplication1 y añadir exactamente el mismo código

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

me sale un error:

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

aunque está en el objeto dinámico.

  • o.Title 'o.Title' produjo una excepción de tipo 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' dinámica {} Microsoft.CSharp.RuntimeBinder.RuntimeBinderException

Aquí está una captura de pantalla: enter image description here

Estoy haciendo algo como esto e intento llamar a la función de película desde un proyecto de prueba.

+1

posible duplicado de [ 'dinámica' no puede acceder a las propiedades de C# de tipos anónimos declaradas en otro conjunto de] (http: // stackoverflow .com/questions/2630370/c-sharp-dynamic-can-no-access-properties-from-anonymous-types-declared-in-anot) –

Respuesta

61

Es necesario utilizar un ExpandoObject

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

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

Se tomó muchas molestias para escribir una elaborada que stion, sería bueno haberle dejado saber por qué está recibiendo el error, ya que Robert sugiere –

+0

¿No parece que puede usar la funcionalidad de inicializador en línea con el objeto expando? –

+0

Excelente, también funciona con pruebas unitarias –

90

respuesta de Jahamal no dice qué se obtiene el error. La razón es que la clase anónima es internal para el ensamblaje. La palabra clave dynamic no le permite omitir la visibilidad del miembro.

La solución es reemplazar la clase anónima con clase pública nombrada.

Aquí hay otro buen ejemplo que explica el motivo y 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

¿Podría citar la fuente en su respuesta, por favor? – d3dave

+0

@ d3dave Las dos afirmaciones en la respuesta se pueden probar. La visibilidad de clase se puede verificar en el descompilador .NET. Las reglas de acceso para 'dynamic' se pueden verificar en una clase de prueba con miembros de visibilidad variable. –

+1

Esta es la verdadera respuesta a por qué lo que OP estaba haciendo es un problema. –

15

En mi caso, yo tenía un proyecto de prueba unitaria que he creado en Visual Studio y una gran cantidad de casos en los que necesitaba para probar métodos en una biblioteca de capa de datos. Yo no quiero cambiar todos ellos así que marcó el conjunto de prueba como un amigo usando:

[assembly: InternalsVisibleTo ("MyDataLayerAssemblyName")]

Y eso lo resolvió.

Ejemplo:

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

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

    [TestClass] 
    public class ContactTests 
    { 
     ... 

Referencias: InternalsVisibleToAttribute Class

Friend Assemblies

+1

La razón es lo que dijo Alexander Stepaniuk. Tu comentario es la solución. ¡Gracias! –

+0

No puedo hacer que esto funcione entre proyectos de netcoreapp1.1, no estoy seguro si es algo que estoy haciendo incorrectamente. –

Cuestiones relacionadas