martes, 27 de mayo de 2014

Receta No. 3-4 en C#: Crear un Tipo y Evitar que Pase los Límites de un Dominio de Aplicación

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
4. Práctica: Código Fuente C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En las dos recetas previas - Crear Tipos que Operen entre Diferentes Dominios de Aplicación, y Mejorar el Rendimiento de una Aplicación Evitando la Carga de Assemblies Innecesarios en Dominios de Aplicación- ya conocemos acerca de las características que deben poseer los tipos (MBR, y MBV) para poder que crucen los límites de un dominio de aplicación. Es el momento adecuado para preparar una receta que vaya en contra de esta posibilidad, es decir, la de evitar que un tipo pase los límites de un dominio. ¡Veamos!

1. Problema

Ya hemos definido en nuestro modelo cuales tipos son los que han sido marcados para operar, es decir, intercambiar mensajes sobre otro dominio de aplicación. Tenemos alrededor de un 15% de tipos que no fueron seleccionados para pasar los límites de su dominio de aplicación local (tipos no-remotos). Ahora, ¿qué debemos hacer marcar a estos tipos como locales?

2. Solución

La solución consiste en obviar la herencia directa o indirecta de MarshalByRefObject, y la omisión del atributo [Serializable] sobre los tipos no-remotos. Esto es lo único que debemos de hacer.

3. Discusión de la Solución

Ya se ha dicho que para evitar que un tipo no trascienda los límites (fronteras, si prefieren) de su dominio, no debemos marcarlo con el atributo [Serializable] [5]: para los tipos pasados por valor (MBV: marshal-by-value). Ahora, para los tipos pasados por referencia (MBR: marshal-by-reference), es necesario que nuestro tipo no herede directa o indirectamente de la clase MarshalByRefObject [4].

Lo anterior nos garantiza que el tipo no pueda ser usado como argumento o tipo de retorno en llamadas a métodos que trasciendan los límites entre dos dominios.

En [1] nos advierte de:
Ensuring that a class cannot be passed by reference requieres a little more attention. Many classes in the .NET class library derive directly or inderectly from MarshalByRefObject; you must be careful you don't inadvertenly derive your class from one of theses.
Adicionalmente, cabe mencionar algunas las clases de la biblioteca .NET que derivan de MarshalByRefObject:
  • System.ComponentModel.Component [6]
  • System.IO.Stream [7]
  • System.IO.TextReader [8]
  • System.Net.WebRequest [9], y 
  • System.Net.WebResponse [10].
En la sección de Jerarquía de Herencia (Inheritance Hierarchy [4]) de la documentación de MarshalByRefObject, se encuentra un listado completo de las tipos que heredan de esta clase abstracta.

4. Práctica: Código Fuente C#

Miremos lo que ocurre cuando intentamos hacer que un tipo (no-remoto) pase los límites de un dominio de aplicación.

Archivo TipoNoRemoto.cs:

Observemos que la clase ClaseNoRemota no posee ninguna de las dos distinciones de objeto remoto, es decir, ni [Serializable] ni herencia de MarshalByRefObject en la línea 23.

En lea línea 42 con el dominio de aplicación nuevoDominio intentamos crear una clase remota. La compilación es correcta:

  1. csc /target:exe TipoNoRemoto.cs

Luego ejecutamos:

  1. .\PruebaTipoNoRemoto.exe

Intento de un tipo no-remoto pasar un límite de un dominio.
Figura 1. Intento de un tipo no-remoto pasar un límite de un dominio.
La excepción System.Runtime.SerializationException [11] es lanzada debido. Esta excepción se dispara en el intento fallido de serialización (marshalling) y deserialización (unmarshalling).

5. Conclusiones

Ha quedado claro que basta con omitir el [Serializable] o la herencia directa o indirecta desde MarshalByRefObject, para evitar que un tipo pase los límites de un dominio de aplicación.

Glosario

  • Atributo
  • Excepción
  • Local
  • MarshalByRefObject
  • Serialización
  • Tipo

Literatura & Enlaces

[1]: Visual C# 2010 Recipes by Allen Jones and Adam Freeman. Copyright 2010 Allen Jones and Adam Freeman, 978-1-4302-2525-6.
[2]: Receta No. 3.2 en C#: Crear Tipos que Operen entre Diferentes Dominios de Aplicación | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/05/receta-no-3-2-en-c-crear-tipos-que-operen-entre-diferentes-dominios-de-aplicacion.html
[3]: Receta No. 3-3 en C#: Mejorar el Rendimiento de una Aplicación Evitando la Carga de Assemblies Innecesarios en Dominios de Aplicación - http://ortizol.blogspot.com/2014/05/receta-no-3-3-en-csharp-mejorar-el-rendimiento-de-una-aplicacion-evitando-la-carga-de-assemblies-innecesarios-en-dominios-de-aplicacion.html
[4]: MarshalByRefObject Class (System) - http://msdn.microsoft.com/en-us/library/system.marshalbyrefobject.aspx
[5]: SerializableAttribute Class (System) - http://msdn.microsoft.com/en-us/library/system.serializableattribute(v=vs.110).aspx
[6]: Component Class (System.ComponentModel) - http://msdn.microsoft.com/en-us/library/system.componentmodel.component(v=vs.110).aspx
[7]: Stream (Clase) (System.IO) - http://msdn.microsoft.com/es-es/library/system.io.stream(v=vs.110).aspx
[8]: TextReader Class (System.IO) - http://msdn.microsoft.com/en-us/library/system.io.textreader(v=vs.110).aspx
[9]: WebRequest Class (System.Net) - http://msdn.microsoft.com/en-us/library/system.net.webrequest(v=vs.110).aspx
[10]: WebResponse Class (System.Net) - http://msdn.microsoft.com/en-us/library/System.Net.WebResponse(v=vs.110).aspx
[11]: SerializationException Class (System.Runtime.Serialization) - http://msdn.microsoft.com/en-us/library/system.runtime.serialization.serializationexception(v=vs.110).aspx


J

No hay comentarios:

Publicar un comentario

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