web-dev-qa-db-fra.com

dynamique ne contient pas de définition d'une propriété à partir d'une référence de projet

Je reçois une erreur qui dit:

'objet' ne contient pas de définition pour 'Titre'

tout le code est aussi sur github

J'ai une ConsoleApplication1 qui ressemble à ceci

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

et Movie.cs

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

cela fonctionne très bien à partir du même projet, mais si j'ajoute ConsoleApplication2 avec une référence à ConsoleApplication1 et que j'ajoute le même code exact

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

Je reçois une erreur:

'objet' ne contient pas de définition pour 'Titre' **

même s'il se trouve dans l'objet dynamique.

  • o.Title 'o.Title' a levé une exception de type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' dynamic {Microsoft.CSharp.RuntimeBinder.RuntimeBinderException}

Voici une capture d'écran: enter image description here

Je fais quelque chose comme ça et j'essaie d'appeler la fonction film à partir d'un projet de test.

78
eiu165

Vous devez utiliser un ExpandoObject

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

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

La réponse de Jahamal ne dit pas pourquoi vous obtenez l'erreur. La raison en est que la classe anonyme est internal pour l'assembly. Le mot clé dynamic ne vous permet pas de contourner la visibilité des membres.

La solution consiste à remplacer la classe anonyme par une classe publique nommée.

Voici un autre bon exemple expliquant la raison et ne autre solution possible .

La raison pour laquelle l'appel à data2.Person échoue, c'est que les informations de type de data2 n'est pas disponible au moment de l'exécution. La raison pour laquelle il n'est pas disponible est que les types anonymes ne sont pas publics. Lorsque la méthode renvoie une instance de ce type anonyme, elle renvoie un System.Object qui fait référence à une instance d'un type anonyme - un type dont les informations ne sont pas disponibles pour le programme principal. Le runtime dynamique essaie de trouver une propriété appelée Person sur l'objet, mais ne peut pas le résoudre à partir des informations de type dont il dispose. En tant que tel, il lève une exception. L'appel à data.Name fonctionne bien puisque Person est une classe publique, cette information est disponible et peut être facilement résolue.

Cela peut vous affecter dans l'un des cas suivants (sinon plus):

  1. Vous renvoyez un type non public et non interne à l'aide de System.Object.
  2. Vous retournez un type dérivé non public et non interne via un type de base public et accédez à une propriété dans le type dérivé qui n'est pas dans le type de base.
  3. Vous renvoyez tout ce qui est enveloppé dans un type anonyme d'un autre assembly.
121
Robert Važan

Dans mon cas, j'avais un projet de test unitaire que j'avais créé sur Visual Studio et beaucoup de cas où j'avais besoin de tester des méthodes sur une bibliothèque de couches de données. Je ne voulais pas tous les changer, j'ai donc marqué l'assemblage de test comme ami en utilisant:

[Assembly: InternalsVisibleTo ("MyDataLayerAssemblyName")]

Et cela l'a résolu.

Exemple:

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

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

   [TestClass]
   public class ContactTests
   {
      ...

Références: Classe InternalsVisibleToAttribute

Assemblées d'amis

23
Jelgab