161 votes

Un type anonyme dynamique dans Razor provoque une RuntimeBinderException

J'obtiens l'erreur suivante :

object" ne contient pas de définition pour "RatingName".

Lorsque vous regardez le type dynamique anonyme, il est clair qu'il possède RatingName.

Screenshot of Error

Je réalise que je peux le faire avec un Tuple, mais j'aimerais comprendre pourquoi le message d'erreur se produit.

245voto

DotNetWise Points 2237

Les types anonymes ayant des propriétés internes sont, à mon avis, une mauvaise décision de conception du framework .NET.

Voici un rapide et belle extension pour résoudre ce problème, c'est-à-dire en convertissant immédiatement l'objet anonyme en un ExpandoObject.

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> anonymousDictionary =  new RouteValueDictionary(anonymousObject);
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (var item in anonymousDictionary)
        expando.Add(item);
    return (ExpandoObject)expando;
}

C'est très facile à utiliser :

return View("ViewName", someLinq.Select(new { x=1, y=2}.ToExpando());

Bien sûr, selon vous :

@foreach (var item in Model) {
     <div>x = @item.x, y = @item.y</div>
}

52voto

JarrettV Points 9099

J'ai trouvé la réponse dans un Question connexe . La réponse est précisée sur le billet de blog de David Ebbo Transmettre des objets anonymes aux vues MVC et y accéder à l'aide de la dynamique

La raison en est que le type anonyme transmis dans le contrôleur est interne, donc il ne peut accessible que depuis l'assemblage dans laquelle il est déclaré. Puisque les vues sont compilées séparément, le liant dynamique dynamique se plaint de ne pas pouvoir dépasser cette limite d'assemblage.

Mais si vous y réfléchissez, cette restriction du liant dynamique est en fait assez artificielle, parce que si vous utilisez la réflexion privée, rien ne vous vous empêche d'accéder à ces membres internes (oui, cela fonctionne même dans confiance moyenne). Ainsi, le liant dynamique par défaut dynamique par défaut fait des pieds et des mains pour appliquer les règles de compilation C# (où vous ne pouvez pas accéder aux membres internes), au lieu de vous laisser faire ce que le CLR le permet.

26voto

alexey Points 2958

Utilisation de ToExpando est la meilleure solution.

Voici la version qui ne nécessite pas System.Web montage :

public static ExpandoObject ToExpando(this object anonymousObject)
{
    IDictionary<string, object> expando = new ExpandoObject();
    foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
    {
        var obj = propertyDescriptor.GetValue(anonymousObject);
        expando.Add(propertyDescriptor.Name, obj);
    }

    return (ExpandoObject)expando;
}

17voto

Simon_Weaver Points 31141

Au lieu de créer un modèle à partir d'un type anonyme, puis d'essayer de convertir l'objet anonyme en un modèle de type ExpandoObject comme ça ...

var model = new 
{
    Profile = profile,
    Foo = foo
};

return View(model);

Vous pouvez simplement créer le ExpandoObject directement à la place.

dynamic model = new ExpandoObject();
model.Profile = profile;
model.Foo = foo;

return View(model);

Ensuite, dans votre vue, vous définissez le type de modèle comme dynamique. @model dynamic et vous pouvez accéder directement aux propriétés :

@Model.Profile.Name
@Model.Foo

Je recommanderais certainement des modèles de vue fortement typés pour la plupart des vues, mais parfois cette flexibilité est pratique.

5voto

jbtule Points 11159

Vous pouvez utiliser le cadre interface impromptue pour envelopper un type anonyme dans une interface.

Il suffit de renvoyer un IEnumerable<IMadeUpInterface> et à la fin de votre Linq, utilisez .AllActLike<IMadeUpInterface>(); cela fonctionne parce qu'il appelle la propriété anonyme en utilisant le DLR avec un contexte de l'assemblage qui a déclaré le type anonyme.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X