Pregunta

¿Cuáles son las diferencias entre System.Dynamic.ExpandoObject, System.Dynamic.DynamicObject y dynamic?

¿En qué situaciones se utilizan estos tipos?

¿Fue útil?

Solución

La palabra clave dynamic se utiliza para las variables de declarar que debe ser tarde con destino a.
Si desea utilizar el enlace en tiempo, para cualquier tipo real o imaginario, se utiliza la palabra clave dynamic y el compilador hace el resto.

Cuando se utiliza la palabra clave dynamic para interactuar con una instancia normal, el llamadas DLR realiza tarde unido a los métodos normales de la instancia.

El IDynamicMetaObjectProvider interfaz permite una clase para tomar el control de su comportamiento finales de ruedas.
Cuando se utiliza la palabra clave dynamic para interactuar con una aplicación IDynamicMetaObjectProvider, el DLR llama a los métodos IDynamicMetaObjectProvider y el objeto mismo decide qué hacer.

Las clases ExpandoObject y DynamicObject son implementaciones de IDynamicMetaObjectProvider.

ExpandoObject es una clase simple que le permite añadir miembros a una instancia y se utilicen dynamically.
DynamicObject es una aplicación más avanzada que puede ser heredada a proporcionar fácilmente el comportamiento personalizado.

Otros consejos

voy a tratar de dar una respuesta clara a esta pregunta, para explicar claramente cuáles son las diferencias entre la dinámica, ExpandoObject y DynamicObject.

Muy rápidamente, dynamic es una palabra clave. No es un tipo per se. Es una palabra clave que le indica al compilador de ignorar la comprobación de tipos estáticos en tiempo de diseño y en lugar de usar enlace tardío en tiempo de ejecución. Por lo que no vamos a pasar mucho tiempo en dynamic en el resto de esta respuesta.

ExpandoObject y DynamicObject son de hecho los tipos. En la superficie, que se ven muy similares entre sí. Ambas clases implementan IDynamicMetaObjectProvider. Sin embargo, cavar más profundo y encontrará que no son similares en todos.

DynamicObject es una implementación parcial de IDynamicMetaObjectProvider puramente destinado a ser un punto de partida para los desarrolladores implementar sus propios tipos de soporte envío dinámico con la costumbre de almacenamiento subyacente y el comportamiento de recuperación para hacer el trabajo de despacho dinámico.

  1. DynamicObject no puede ser construido directamente.
  2. debe extender DynamicObject para que tenga alguna utilidad para usted como el desarrollador.
  3. Cuando se extiende DynamicObject que ahora son capaces de proporcionar un comportamiento personalizado con respecto a cómo desea envío dinámico para resolver a los datos almacenados internamente en su representación de datos subyacente en tiempo de ejecución.
  4. tiendas ExpandoObject datos en un diccionario, etc. subyacentes Si implementa DynamicObject, que puede almacenar datos donde y similares. (Por ejemplo, cómo obtener y establecer los datos de expedición es totalmente de usted).

En resumen, el uso DynamicObject cuando desee crear sus propios tipos que se pueden utilizar con el DLR y el trabajo con cualquier comportamientos personalizados desea.

Ejemplo: Imagine que le gustaría tener un tipo dinámico que vuelve una costumbre cada vez que un defecto get se trató de un miembro que no existe (es decir, no se ha añadido en tiempo de ejecución). Y que por defecto va a decir, "Lo siento, no hay cookies en este frasco!". Si desea que un objeto dinámico que se comporta como este, tendrá que controlar lo que ocurre cuando no se encuentra un campo. ExpandoObject no va a dejar de hacer esto. Por lo que usted necesita para crear su propio tipo de comportamiento único miembro de resolución dinámico (despacho) y el uso que en lugar de la ExpandoObject que ya están construidos.

Se puede crear un tipo de la siguiente manera: (.. Tenga en cuenta, el siguiente código es sólo para ilustración y no se ejecute Para obtener información sobre cómo utilizar correctamente DynamicObject, hay muchos artículos y tutoriales en otro lugar)

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

Ahora, podríamos utilizar esta clase imaginaria que acabamos de crear como un tipo dinámico que tiene un comportamiento muy personalizada si el campo no existe.

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 es una implementación completa de IDynamicMetaObjectProvider, donde el equipo de .NET Framework ha hecho todas estas decisiones por usted. Esto es útil si usted no necesita ningún comportamiento personalizado, y usted siente que ExpandoObject funciona lo suficientemente bueno para usted (el 90% de las veces, ExpandoObject es lo suficientemente bueno). Así, por ejemplo, ver el siguiente, y que por ExpandoObject, los diseñadores optaron por lanzar una excepción si el miembro dinámico no existe.

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

Entonces, para resumir, ExpandoObject es simplemente una forma de pre-elegido para extender DynamicObject con ciertos comportamientos de despacho dinámicos que probablemente va a funcionar para usted , pero puede que no en función de sus necesidades particulares.

Mientras, DyanmicObject es un BaseType ayudante que hace que la implementación de sus propios tipos de comportamientos dinámicos con singular simple y fácil.

Un tutorial útil sobre la que gran parte de la fuente ejemplo anterior se basa.

De acuerdo con la especificación del lenguaje C # dynamic es una declaración de tipo. Es decir. dynamic x significa el x variable tiene el tipo dynamic.

DynamicObject es un tipo que hace que sea fácil de implementar IDynamicMetaObjectProvider y así anular el comportamiento de unión para el tipo específico.

ExpandoObject es un tipo que actúa como una bolsa de propiedades. Es decir. se pueden añadir propiedades, métodos y así sucesivamente a instancias dinámicas de este tipo en tiempo de ejecución.

El ejemplo anterior de DynamicObject no le dice a la diferencia con claridad, porque es básicamente la implementación de la funcionalidad que ya está proporcionada por ExpandoObject.

En los dos enlaces se mencionan a continuación, es muy claro que con la ayuda de DynamicObject, es posible preservar / cambiar el tipo real (XElement en el ejemplo utilizado en debajo de enlaces) y un mejor control sobre las propiedades y métodos.

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;    
        }    
    }    
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top