Esta es la parte final de la serie
Dynamic Language Runtime . Artículos anteriores:
- Detalle dinámico: juegos encubiertos del compilador, pérdida de memoria, matices de rendimiento . Este artículo analiza la caché DLR en detalle y los puntos que son importantes para el desarrollador.
- Grokl DLR . Una descripción general de la tecnología, la disección de DynamicMetaObject y una breve instrucción sobre cómo crear su propia clase dinámica.
En este breve artículo, finalmente analizaremos los principales casos de uso
dinámico en la vida real: cuándo no puede prescindir de él y cuándo puede hacer la vida mucho más fácil.

Cuando la dinámica es indispensable
No hay tales casos. Siempre puede escribir código de funcionalidad similar en un estilo estático, la única diferencia es la facilidad de lectura y la cantidad de código. Por ejemplo, cuando trabaje con objetos COM, en lugar de
dinámico, puede usar la reflexión.
Cuando dinámico es útil
Trabajar con objetos COM
En primer lugar, esto, por supuesto, es trabajar con objetos COM, por lo cual se inició todo esto. Compare el código obtenido con
dinámica y reflexión:
dynamic instance = Activator.CreateInstance(type); instance.Run("Notepad.exe");
var instance = Activator.CreateInstance(type); type.InvokeMember("Run", BindingFlags.InvokeMethod, null, instance, new[] { "Notepad.exe" });
Como regla general, para trabajar con objetos COM a través de la reflexión, debe crear clases ramificadas con contenedores para cada método / propiedad. También hay cosas menos obvias, como la capacidad de no completar los parámetros que no necesita (obligatorio desde el punto de vista de un objeto COM) al llamar a un método a través de la
dinámica .
Trabajar con configuraciones
Otro ejemplo de libro de texto está trabajando con configuraciones, como
XML . Sin
dinámica :
XElement person = XElement.Parse(xml); Console.WriteLine( $"{person.Descendants("FirstName").FirstOrDefault().Value} {person.Descendants("LastName").FirstOrDefault().Value}" );
Con dinámica:
dynamic person = DynamicXml.Parse(xml); Console.WriteLine( $"{person.FirstName} {person.LastName}" );
Por supuesto, para esto necesita implementar su propia clase dinámica. Como alternativa a la primera lista, puede escribir una clase que funcione de la siguiente manera:
var person = StaticXml.Parse(xml); Console.WriteLine( $"{person.GetElement("FirstName")} {person.GetElement("LastName")}" );
Pero, ya ves, esto se ve mucho menos elegante que a través de la
dinámica .
Trabajar con recursos externos.
El párrafo anterior se puede generalizar a cualquier acción con recursos externos. Siempre tenemos dos alternativas: usar
dinámico para obtener el código en estilo nativo de C # o escribir estático con "líneas mágicas". Veamos un ejemplo con una solicitud de
API REST . Con Dynamic, puedes escribir esto:
dynamic dynamicRestApiClient = new DynamicRestApiClient("http://localhost:18457/api"); dynamic catsList = dynamicRestApiClient.CatsList;
Donde nuestra clase dinámica enviará una solicitud del formulario a solicitud de la propiedad
[GET] http://localhost:18457/api/catslist
Luego lo deserializa y nos devuelve una serie de gatos que ya están listos para el uso previsto. Sin
dinámica, se vería así:
var restApiClient = new RestApiClient("http://localhost:18457/api"); var catsListJson = restApiClient.Get("catsList"); var deserializedCatsList = JsonConvert.DeserializeObject<Cat[]>(catsListJson);
Reemplazo de reflejo
En el ejemplo anterior, puede tener una pregunta: ¿por qué en un caso estamos deserializando el valor de retorno a un tipo específico, y en el otro no? El hecho es que en la escritura estática necesitamos convertir explícitamente objetos al tipo
Cat para trabajar con ellos. En el caso de la
dinámica , es suficiente deserializar
JSON en una matriz de objetos dentro de nuestra clase dinámica y devolver el
objeto [] , ya que
dinámica se encarga de la reflexión. Daré dos ejemplos de cómo funciona esto:
dynamic deserialized = JsonConvert.DeserializeObject<object>(serialized); var name = deserialized.Name; var lastName = deserialized.LastName;
Attribute[] attributes = type.GetCustomAttributes(false).OfType<Attribute>(); dynamic attribute = attributes.Single(x => x.GetType().Name == "DescriptionAttribute"); var description = attribute.Description;
El mismo principio que cuando se trabaja con objetos COM.
Visitante
Usando
dinámico, puede implementar de manera muy elegante este patrón. En lugar de mil palabras:
public static void DoSomeWork(Item item) { InternalDoSomeWork((dynamic) item); } private static void InternalDoSomeWork(Item item) { throw new Exception("Couldn't find handler for " + item.GetType()); } private static void InternalDoSomeWork(Sword item) {
Ahora, al pasar un objeto de tipo
Sword al método
DoSomeWork , se
llamará al método
InternalDoSomeWork (elemento Sword) .
Conclusiones
Ventajas de usar
dinámico :
- Se puede usar para la creación rápida de prototipos: en la mayoría de los casos, el número de código repetitivo disminuye
- Como regla, mejora la legibilidad y la estética (debido a la transición de "líneas mágicas" al estilo nativo del lenguaje) del código
- A pesar de la opinión generalizada, gracias a los mecanismos de almacenamiento en caché, no surge una sobrecarga de rendimiento significativa en el caso general
Contras de usar dinámico:
- Hay matices no evidentes asociados con la memoria y el rendimiento.
- Con el apoyo y la lectura de tales clases dinámicas, debe comprender bien lo que está sucediendo.
- El programador está privado de la verificación de tipo y de todas las garantías de salud proporcionadas por el compilador.
Conclusión
En mi opinión, el desarrollador recibirá el mayor beneficio del uso dinámico en las siguientes situaciones:
- Cuando prototipos
- En proyectos pequeños / domésticos donde el costo del error es bajo
- En pequeñas utilidades de tamaño de código que no implican un tiempo de ejecución prolongado. Si su utilidad se ejecuta en el peor de los casos durante unos segundos, generalmente no hay necesidad de pensar en pérdidas de memoria y degradación del rendimiento
Al menos controvertido es el uso de la
dinámica en proyectos complejos con una gran base de código; aquí es mejor pasar tiempo escribiendo envoltorios estáticos, minimizando así la cantidad de momentos no obvios.
Si trabaja con objetos COM o dominios en servicios / productos que implican un tiempo de trabajo largo y continuo, es mejor no utilizar la
dinámica , a pesar del hecho de que se creó para tales casos. Incluso si sabe a fondo qué y cómo hacer y nunca comete errores, tarde o temprano puede llegar un nuevo desarrollador que no lo sabe. Es probable que el resultado sea una pérdida de memoria difícil de calcular.