domingo, 5 de julio de 2015

Enlace Dinámico en C# - Parte 2: Enlace de Lenguaje y Personalizado

Índice

0. Introducción
1. Enlace Personalizado
2. Enlace de Lenguaje
3. Conclusiones
4. Glosario
5. Literatura & Enlaces

0. Introducción

Segunda parte de la serie de artículos C# dedicada a Enlace Dinámico. En esta ocasión veremos una característica importante a la hora de crear objetos que adquieren comportamiento y estado adicionales en tiempo de ejecución; para ello debemos empezar a conocer la interfaz IDynamicMetaObjectProvider y un par de clases de la BCL que la implementan: ExpandoObject, y DynamicObject. Esta interfaz es capaz de proveer dinamismo a los tipos de objetos que el programador cree en su dominio. También conoceremos su utilidad en el tratamiento de tipos de lenguajes dinámicos como IronPython y IronRuby, los cuales están construidos bajo la base de Dynamic Language Runtime (DLR).


Por otro lado, haremos una breve introducción acerca del Enlace de Lenguaje: técnica útil para objetos dinámicos que no implementan la interfaz IDynamicMetaObjectProvider.
  1. Introducción al Enlace Dinámico, Enlace estático vs enlace dinámico, RuntimeBinderException
  2. Enlace Personalizado, Enlace de Lenguaje
  3. La Palabra Clave dynamic, Conversiones, Diferencia entre var y dynamic
  4. Expresiones Dinámicas, Expresiones Dinámicas sin Receptores Dinámicos
  5. Tipos Estáticos en Expresiones Dinámicas, Funciones Non-Invocables

1. Enlace Personalizado

Empecemos por introducir un ejemplo de uso para que se nos facilite entender el enlace personalizado. En este ejemplo usaremos una de las implementaciones concretas de la interfaz IDynamicMetaObjectProvider [2] (IDMOP): DynamicObject [4]. Veamos esta jerarquía de herencia:
Jerarquía de herencia e implementación Enlace Personalizado
Figura 1. Jerarquía de herencia e implementación Enlace Personalizado.
Notemos como la clase Avion hereda de la clase concreta DynamicObject. Esta operación de herencia nos va a permitir sobreescribir el método TryInvokeMember(InvokeMemberBinder, object[], object) [5]. Es esta sobreescritura la que permitirá adicionar llamadas a métodos en tiempo de ejecución.


Ahora hagamos el ejercicio de implementar esta jerarquía de herencia en código fuente C#:

Archivo C# Avion.cs [Enlace alternativo]:



En la línea 4 heredamos de DynamicObject sobre la clase Avion. Sobrescribimos (override) el método TryInvokeMember para demostrar la invocación de métodos de forma dinámica (líneas 6-12). En la clase AvionPrueba (líneas 15-28) creamos una variable del tipo dynamic llamada avionDyn (línea 21). Sobre esta variable invocamos los miembros Despegar y Aterrizar, líneas 23 y 24, respectivamente. En estas dos líneas es donde efectivamente se evidencia la utilidad de la invocación dinámica de miembros.

Compilación:


  1. csc /target:exe UnicaInstanciaAplicacion.cs

Ejecución assembly:


  1. .\UnicaInstanciaAplicacion.exe

> Prueba de ejecución (ideone.com).

> Prueba e ejecución (local):
Ejecución assembly Avion.exe
Figura 2. Ejecución assembly Avion.exe.

Ahora ya que contamos con una intuición sobre la ventaja de manipular miembros de forma dinámica, pasemos a nombrar otros escenarios de aplicación importantes y posibles.


En contexto, la interfaz IDynamicMetaObjectProvider es fundamental para la manipulación de objetos de lenguajes de programación compatibles con Microsoft .NET Framework: IronPython, IronRuby. Estos lenguajes están implementados bajo la DLR (Dynamic Language Runtime) y de forma implícita implementan la interfaz IDynamicMetaObjectProvider. (Para conocer más acerca de la DLR recomiendo la lectura Comprobación de Tipos en Tiempo de Compilación y Ejecución en C#.)

2. Enlace de Lenguaje

Como se explicita en [1]:
"Language binding occurs when a dynamic object does not implement IDynamicMetaObjectProvider."
Entre los escenarios básicos de utilidad de este tipo de lenguaje se enumeran [1]:
  • Tipos diseñados con imperfecciones (e.g., resultado de tradeoffs impuestos en el diseño.)
  • Limitaciones inherentes en el sistema de tipos de .NET.
Recurramos al ejemplo básico de uso de tipo de retorno dinámico presentando en la demostración de [1]:

Archivo C# SinInterfazComun.cs [Enlace alternativo]:



Notemos que en las líneas 16-19 tenemos el siguiente método:

public static dynamic Promedio(dynamic x, dynamic y)
{
return (x + y) / 2;
}


Este método lo podemos ver como una abstracción para calcular el promedio de cualquier valor de las categorías de tipos primitivos (o integrales), es decir, podríamos pasar como argumento valores de tipo Int32, Int64, o double, etc.Además, esta implementación con tipo de retorno y tipos de argumentos dinámicos resuelve la carencia de una interfaz común para los tipos numéricos.


A diferencia de las otras dos firmas (líneas 21-24, y 26-28) con tipos de retorno y tipos de argumentos específicas, la versión dinámica presenta la ventaja de remoción de código duplicado. Por otra parte, en [1] resaltan:
"However, you lose static type safety, risking runtime exceptions rather than compile time errors."
Compilación:


  1. csc /target:exe SinInterfazComun.cs

Ejecución assembly:


  1. .\SinInterfazComun.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local):
Ejecución assembly SinInterfazComun.exe
Figura 3. Ejecución assembly SinInterfazComun.exe.

3. Conclusiones

Hemos explorado el concepto de Enlace Personalizado, el cual nos es útil para la creación de objetos dinámicos, como vimos en el ejemplo: agregación de métodos como Despegar y Aterrizar en tiempo de ejecución para un objeto del tipo personalizado Avion. Inclusive, nos informamos que otro de los escenarios en donde la implementación de enlaces personalizados con la interfaz IDynamicMetaObjectProvider, nos facilita interactuar con objetos de lenguajes dinámicos como IronPython y IronRuby. En la segunda parte, descubrimos el enlace de lenguaje para solucionar aquellas carencias de diseño en el sistema de tipos de .NET.


En la tercera parte centraremos nuestra atención en el uso de la palabra clave dynamic, conversiones, y un versus entre dynamic y var.

4. Glosario

  • .NET
  • BCL
  • Dinamismo
  • Dynamic
  • Enlace de lenguaje
  • Enlace personalizado
  • Interfaz
  • Objeto

5. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: IDynamicMetaObjectProvider Interface (System.Dynamic) - https://msdn.microsoft.com/en-us/library/system.dynamic.idynamicmetaobjectprovider(v=vs.110).aspx
[3]: Receta No. 1-19 en C#: Creación de un Tipo Dinámico usando ExpandoObject - http://ortizol.blogspot.com/2014/02/receta-no-1-19-en-c-creacion-de-un-tipo.html
[4]: DynamicObject Class (System.Dynamic) - https://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject(v=vs.110).aspx
[5]: DynamicObject.TryInvokeMember Method (System.Dynamic) - https://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.tryinvokemember(v=vs.110).aspx
[6]: Comprobación de Tipos en Tiempo de Compilación y Ejecución en C# - http://ortizol.blogspot.com/2014/03/comprobacion-de-tipos-en-tiempo-de.html


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.