Question

Quelles sont les différences entre System.Dynamic.ExpandoObject, System.Dynamic.DynamicObject et dynamic?

Dans quelles situations utilisez-vous ces types?

Était-ce utile?

La solution

Le mot-clé dynamic est utilisé pour les variables doivent être DÉCLARE que la liaison tardive.
Si vous souhaitez utiliser la liaison tardive, pour tout type réel ou imaginé, vous utilisez le mot-clé dynamic et le compilateur fait le reste.

Lorsque vous utilisez le mot-clé dynamic pour interagir avec une instance normale, le noreferrer DLR les appels de fin effectue-liés à des méthodes normales de l'instance.

Le IDynamicMetaObjectProvider l'interface permet à une classe de prendre le contrôle de son comportement tardif lié.
Lorsque vous utilisez le mot-clé dynamic pour interagir avec une implémentation IDynamicMetaObjectProvider, le DLR appelle les méthodes de IDynamicMetaObjectProvider et l'objet lui-même décide ce qu'il faut faire.

Les classes ExpandoObject et DynamicObject sont mises en œuvre de IDynamicMetaObjectProvider.

ExpandoObject est une classe simple qui vous permet d'ajouter des membres à une instance et de les utiliser dynamically.
DynamicObject est une implémentation plus avancée qui peut être hérité facilement fournir un comportement personnalisé.

Autres conseils

Je vais essayer de fournir une réponse plus claire à cette question, d'expliquer clairement quelles sont les différences entre les dynamiques, ExpandoObject et DynamicObject.

Très vite, dynamic est un mot-clé. Il est pas un type par-soi. Il est un mot clé qui indique au compilateur d'ignorer la vérification de type statique à la conception du temps et au lieu d'utiliser contraignant fin lors de l'exécution. Donc, on ne va pas passer beaucoup de temps sur dynamic dans le reste de cette réponse.

ExpandoObject et DynamicObject sont en effet types. Sur la surface, ils se ressemblent les uns aux autres. Les deux classes implémentent IDynamicMetaObjectProvider. Cependant, creuser plus profond et vous trouverez qu'ils ne sont pas du tout semblable.

DynamicObject est une mise en œuvre partielle de IDynamicMetaObjectProvider purement destiné à être un point de départ pour les développeurs d'implémenter leurs propres types de soutien dispatch dynamique avec stockage sous-jacent personnalisé et le comportement de récupération pour rendre le travail de répartition dynamique.

  1. DynamicObject ne peut pas être construit directement.
  2. Vous devez étendre DynamicObject pour qu'il ait une quelconque utilité pour vous en tant que développeur.
  3. Lorsque vous étendez DynamicObject vous êtes maintenant en mesure de fournir un comportement personnalisé sur la façon dont vous voulez l'envoi dynamique pour résoudre les données stockées en interne dans votre représentation de données sous-jacentes à l'exécution.
  4. stocke ExpandoObject données sous-jacentes dans un dictionnaire, etc. Si vous implémentez DynamicObject, vous pouvez stocker des données partout et cependant vous aimez. (Par exemple la façon dont vous obtenez et définissez les données sur l'envoi est entièrement à vous).

En bref, l'utilisation DynamicObject lorsque vous souhaitez créer vos propres types qui peuvent être utilisés avec le DLR et travailler avec tous les comportements personnalisés que vous souhaitez.

Exemple: Imaginez que vous souhaitez avoir un type de dynamique qui renvoie un défaut personnalisé à chaque fois qu'un get est tentée sur un membre qui n'existe pas (à savoir n'a pas été ajouté au moment de l'exécution). Et ce défaut dira: « Je suis désolé, il n'y a pas les cookies dans ce pot! ». Si vous voulez un objet dynamique qui se comporte comme cela, vous aurez besoin de contrôler ce qui se passe lorsqu'un champ est introuvable. ExpandoObject ne vous laissera pas faire. Donc, vous devrez créer votre propre type de comportement de résolution de membre dynamique unique (expédition) et utiliser à la place du ExpandoObject prêt à l'emploi.

Vous pouvez créer un type comme suit: (.. Remarque, le ci-dessous le code est juste pour illustration et ne peut pas courir Pour en savoir plus sur la façon d'utiliser correctement DynamicObject, il y a de nombreux articles et tutoriels ailleurs)

public class MyNoCookiesInTheJarDynamicObject : DynamicObject
{
    Dictionary<string, object> properties = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (properties.ContainsKey(binder.Name))
        {
            result = properties[binder.Name];
            return true;
        }
        else
        {
            result = "I'm sorry, there are no cookies in this jar!"; //<-- THIS IS OUR 
            CUSTOM "NO COOKIES IN THE JAR" RESPONSE FROM OUR DYNAMIC TYPE WHEN AN UNKNOWN FIELD IS ACCESSED
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        properties[binder.Name] = value;
        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        dynamic method = properties[binder.Name];
        result = method(args[0].ToString(), args[1].ToString());
        return true;
    }
}

Maintenant, nous pourrions utiliser cette classe imaginaire que nous venons de créer comme un type de dynamique qui a un comportement très personnalisé si le champ n'existe pas.

dynamic d = new MyNoCookiesInTheJarDynamicObject();
var s = d.FieldThatDoesntExist;

//in our contrived example, the below should evaluate to true
Assert.IsTrue(s == "I'm sorry, there are no cookies in this jar!")

ExpandoObject est une mise en œuvre intégrale de IDynamicMetaObjectProvider, où l'équipe .NET Framework a fait toutes ces décisions pour vous. Ceci est utile si vous ne avez pas besoin de comportement personnalisé, et vous vous sentez que ExpandoObject fonctionne assez bon pour vous (90% du temps, ExpandoObject est assez bon). Ainsi, par exemple, voir ce qui suit, et que pour ExpandoObject, les concepteurs ont choisi de lancer une exception si l'élément dynamique n'existe pas.

dynamic d = new ExpandoObject();

/*
The ExpandoObject designers chose that this operation should result in an 
Exception. They did not have to make that choice, null could 
have been returned, for example; or the designers could've returned a "sorry no cookies in the jar" response like in our custom class. However, if you choose to use 
ExpandoObject, you have chosen to go with their particular implementation 
of DynamicObject behavior.
*/

try {
var s = d.FieldThatDoesntExist;
}
catch(RuntimeBinderException) { ... }

Donc, pour résumer, ExpandoObject est tout simplement une façon choisie avant d'étendre DynamicObject avec certains comportements d'expédition de dynamique qui fonctionnera probablement pour vous , mais ne peut pas en fonction de vos besoins particuliers.

Alors, DyanmicObject est un BaseType d'aide qui fait la mise en œuvre de vos propres types avec des comportements dynamiques uniques simple et facile.

Un tutoriel utile sur lequel une grande partie de la source d'exemple ci-dessus est basée.

Selon la spécification du langage C # dynamic est une déclaration de type. C'est à dire. dynamic x signifie que la variable a la x dynamic de type.

DynamicObject est un type qui le rend facile à mettre en œuvre IDynamicMetaObjectProvider et donc passer outre le comportement de liaison spécifique pour le type.

ExpandoObject est un type qui agit comme un sac de propriété. C'est à dire. vous pouvez ajouter des propriétés, méthodes et ainsi de suite aux instances dynamiques de ce type à l'exécution.

L'exemple ci-dessus DynamicObject ne dit pas clairement la différence, parce qu'elle est mise en œuvre essentiellement la fonctionnalité qui est déjà fournie par ExpandoObject.

Dans les deux liens mentionnés ci-dessous, il est très clair que, avec l'aide de DynamicObject, il est possible de préserver / changer le type réel (XElement dans l'exemple utilisé en liens ci-dessous) et un meilleur contrôle sur les propriétés et méthodes.

https://blogs.msdn.microsoft.com/csharpfaq/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject/

public class DynamicXMLNode : DynamicObject    
{    
    XElement node;

    public DynamicXMLNode(XElement node)    
    {    
        this.node = node;    
    }

    public DynamicXMLNode()    
    {    
    }

    public DynamicXMLNode(String name)    
    {    
        node = new XElement(name);    
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)    
    {    
        XElement setNode = node.Element(binder.Name);

        if (setNode != null)    
            setNode.SetValue(value);    
        else    
        {    
            if (value.GetType() == typeof(DynamicXMLNode))    
                node.Add(new XElement(binder.Name));    
            else    
                node.Add(new XElement(binder.Name, value));    
        }

        return true;    
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)    
    {    
        XElement getNode = node.Element(binder.Name);

        if (getNode != null)    
        {    
            result = new DynamicXMLNode(getNode);    
            return true;    
        }    
        else    
        {    
            result = null;    
            return false;    
        }    
    }    
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top