Domanda

Quali sono le differenze tra System.Dynamic.ExpandoObject, System.Dynamic.DynamicObject e dynamic?

In quali situazioni si usa questo tipo?

È stato utile?

Soluzione

La parola chiave dynamic viene utilizzata per le variabili di dichiarazione che dovrebbe essere tardiva.
Se si desidera utilizzare l'associazione tardiva, per qualsiasi tipo reale o immaginario, si utilizza la parola chiave dynamic e il compilatore fa il resto.

Quando si utilizza la parola chiave dynamic di interagire con un'istanza normale, il noreferrer chiamate DLR esegue tardiva ai metodi normali dell'istanza.

Il IDynamicMetaObjectProvider interfaccia consente una classe di prendere il controllo del suo comportamento tardo-bound.
Quando si utilizza la parola chiave dynamic di interagire con un'implementazione IDynamicMetaObjectProvider, DLR chiama i metodi IDynamicMetaObjectProvider e l'oggetto stesso decide cosa fare.

Le classi ExpandoObject e DynamicObject sono implementazioni di IDynamicMetaObjectProvider.

ExpandoObject è una semplice classe che consente di aggiungere i membri a un'istanza e utilizzarli dynamically.
DynamicObject è un'implementazione più avanzato che può essere ereditata al comportamento facilmente concedono.

Altri suggerimenti

I cercherà di fornire una risposta chiara a questa domanda, di spiegare chiaramente quali siano le differenze tra le dinamiche, ExpandoObject e DynamicObject.

Molto rapidamente, dynamic è una parola chiave. Non è un tipo per sé. Si tratta di una parola chiave che dice al compilatore di ignorare controllo di tipo statico in fase di progettazione e invece di usare late-binding in fase di esecuzione. Quindi non stiamo andando a spendere molto tempo su dynamic nel resto di questa risposta.

ExpandoObject e DynamicObject sono davvero tipi. In superficie, sembrano molto simili tra loro. Entrambe le classi implementano IDynamicMetaObjectProvider. Tuttavia, scavare più a fondo e troverete che non sono simili a tutti.

DynamicObject è un'implementazione parziale di IDynamicMetaObjectProvider puramente doveva essere un punto di partenza per sviluppatori di implementare i propri tipi personalizzati di supporto dinamico spedizione con sottostanti un'archiviazione personalizzata e comportamento recupero per far funzionare distribuzione dinamica.

  1. DynamicObject non può essere costruito direttamente.
  2. è necessario estendere DynamicObject affinchè abbia alcuna utilità per voi come lo sviluppatore.
  3. Quando si estende DynamicObject si sono ora in grado di fornire comportamento personalizzato per quanto riguarda la modalità di spedizione dinamica per volontà di dati memorizzati internamente nella rappresentazione di dati sottostante in fase di esecuzione.
  4. memorizza ExpandoObject sottostanti i dati in un dizionario, ecc Se si implementa DynamicObject, è possibile memorizzare i dati dove e come più vi piace. (Ad esempio, come si ottiene e impostare i dati alla spedizione è interamente a voi).

In breve, l'uso DynamicObject quando si desidera creare i tipi PROPRIE che possono essere utilizzati con la DLR e lavorare con qualunque comportamenti personalizzati vuoi.

Esempio: Immaginate che si desidera avere un tipo dinamico che restituisce un predefinito personalizzato ogni volta che un get è tentata su un membro che non esiste (cioè non è stato aggiunto in fase di esecuzione). E che di default dirà: "Mi dispiace, non ci sono i cookie in questo vaso!". Se si desidera un oggetto dinamico che si comporta come questo, avrete bisogno di controllare ciò che accade quando un campo non viene trovato. ExpandoObject non ti consente di fare questo. Quindi, è necessario creare un tipo con unica risoluzione membro dinamico (invio) il comportamento e l'uso che al posto del ExpandoObject ready-built.

È possibile creare un tipo come segue: (.. Nota, il sottostante Codice è solo per l'illustrazione e non possono eseguire Per informazioni su come usare correttamente DynamicObject, ci sono molti articoli e tutorial altrove)

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

Ora, potremmo usare questa classe immaginaria che abbiamo appena creato come un tipo dinamico che ha un comportamento personalizzato molto se il campo non esiste.

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 è un'implementazione completa di IDynamicMetaObjectProvider, dove la squadra .NET Framework ha fatto tutte queste decisioni per voi. Questo è utile se non è necessario alcun comportamento personalizzato, e si sente che ExpandoObject funziona abbastanza buono per voi (il 90% del tempo, ExpandoObject è abbastanza buono). Così, per esempio, si veda il successivo, e che per ExpandoObject, i progettisti hanno scelto di un'eccezione se il membro dinamico non esiste.

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) { ... }

Quindi, per riassumere, ExpandoObject è semplicemente un modo pre-scelto di estendere DynamicObject con certi comportamenti di spedizione dinamiche che probabilmente funzionerà per voi , ma non può a seconda delle esigenze particolari.

considerando che, DyanmicObject è un BaseType aiutante che rende attuare i propri tipi con comportamenti dinamici unico semplice e facile.

Un tutorial utile su cui gran parte della sorgente di esempio sopra si riferiscono.

Secondo il C # specifiche del linguaggio dynamic è una dichiarazione di tipo. Cioè dynamic x intende il x variabile ha il tipo dynamic.

DynamicObject è un tipo che rende facile implementare IDynamicMetaObjectProvider e prevalga pertanto specifico comportamento vincolante per il tipo.

ExpandoObject è un tipo che si comporta come un elenco di proprietà. Cioè è possibile aggiungere le proprietà, i metodi e così via per istanze dinamiche di questo tipo in fase di esecuzione.

L'esempio precedente DynamicObject non dice chiaramente la differenza, perché è fondamentalmente attuazione della funzionalità che è già provvisto da ExpandoObject.

Nei due link sottostanti, è evidente che con l'aiuto di DynamicObject, è possibile conservare / modificare il tipo effettivo (XElement nell'esempio utilizzato in seguito pubblicitari) e un migliore controllo sulle proprietà e metodi.

https://blogs.msdn.microsoft.com/csharpfaq/2009/09/30/dynamic-in-c-4-0-introducing-the-expandoobject/

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;    
        }    
    }    
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top