Integración de Sistemas

Transcripción

Integración de Sistemas
Integración de Sistemas
Unity
Integración de Sistemas
Parte II. Diseño e implementación de
aplicaciones Web con .NET
Unity
Dependencias a alto nivel
Interfaz de Usuario
Depende de
Capa lógica / Capa de Negocio
Depende de
Capa de Acceso a Datos
Depende de
Database
Curso 2008 - 2009
1
Integración de Sistemas
Unity
Ejemplo de dependencia
public void RegisterUser(String loginName, String clearPassword,
UserProfileDetailsVO userProfileDetailsVO)
{
<...>
DbConnection connection = (DbConnection) new SQLConnection();
<...>
IUserProfileDAO dao = (IUserProfileDAO) new UserProfileDAO();
String encryptedPassword = Crypto.crypt(clearPassword);
UserProfileVO userProfileVO = new UserProfileVO(loginName,
encryptedPassword, userProfileDetailsVO);
dao.Create(connection, transaction, userProfileVO);
<...>
}
Unity
Problemas originados por las dependencias
„
Código altamente acoplado
„
Aislamiento de código se complica
…
„
Mantenimiento complejo
…
Curso 2008 - 2009
Se dificulta la realización de las pruebas
Desconocimiento acerca de los efectos colaterales de la
modificación de código.
2
Integración de Sistemas
Unity
Problemas originados por las dependencias: soluciones
„
Solución 1: Delegar en factorías la generación de instancias que
puedan derivar en dependencias
public void RegisterUser(String loginName, String clearPassword,
UserProfileDetailsVO userProfileDetailsVO)
{
<...>
DbDconnection connection = dbProviderFactory.CreateConnection();
<...>
IUserProfileDAO dao = UserProfileDAOFactory.GetDAO();
String encryptedPassword = Crypto.crypt(clearPassword);
UserProfileVO userProfileVO = new UserProfileVO(loginName,
encryptedPassword, userProfileDetailsVO);
Leerá la de un fichero de
configuración el nombre
de la instancia correcta
dao.Create(connection, transaction, userProfileVO);
<...>
}
Unity
Problemas originados por las dependencias: soluciones
„
Solución 1: Delegar en factorías la generación de instancias que
puedan derivar en dependencias
„
Inconvenientes:
o
Permanece la dependencia con respecto a la propia factoría
o
o
Curso 2008 - 2009
Además, el código es dependiente de la Interfaz
proporcionada por la factoría
Distribución código implica la distribución de la factoría
o
Externo a la lógica del negocio
o
Codificación de la factoría es específica a cada problema
3
Integración de Sistemas
Unity
Problemas originados por las dependencias: soluciones
„
Solución 2: Inyección de Dependencias / Inversión de Control (IoC)
„
Principio Hollywoold
„
„
Don`t call us, we’ll call you
„
No nos llame, nosotros le llamaremos
Los propios objetos conocen los recursos de los que deben hacer
uso para su correcto funcionamiento
„
Delegan en el entorno para acceder a dichos recursos
„
entorno = framework de inversión de control (IoC container)
Unity
Problemas originados por las dependencias: soluciones
„
Solución 2: Inyección de Dependencias
public void RegisterUser(String loginName, String clearPassword,
UserProfileDetailsVO userProfileDetailsVO)
{
<...>
IUserProfileDAO dao = container.Resolve(<IUserProfileDAO>);
<...>
}
Leerá la de un fichero de
configuración (o se indicará al
container por código) el mapeado
de clases correcto
Curso 2008 - 2009
4
Integración de Sistemas
Unity
Problemas originados por las dependencias: soluciones
public interface IUserService
{
[Dependency]
IUserProfileDao UserProfileDAO { set; }
<...>
}
public class TestUserProfile
{
public static void Main(string[] args)
{
<...>
IUserService userService = container.Resolve<IUserService>();
/*
* The dao used within the UserService object is
* created by means of IoC, so it is not necessary to resolve it
*
* userService.dao = container.Resolve<IUserProfileDao>();
*/
<...>
}
}
Unity
Instanciación y configuración del Contedor
„
Contenedor almacenará las referencias a las clases o
instancias que posteriormente se inyectarán
„
Permitirá configurar la inyección de cada dependencia
„
Configuración posible directamente a través de código o bien
a través
t é d
de xmll
„
¿Cuándo se crea el contenedor?
„
Curso 2008 - 2009
Al inicio de la ejecución: global.asax
5
Integración de Sistemas
Unity
Instanciación y configuración del Contedor
Configuración a través de código: registro de tipos
„
#region Get DAO (Option 2): Configure DAO Injection by code.
// Instanciación del contenedor
IUnityContainer container = new UnityContainer();
// Registro de instancias
container.RegisterType<IUserProfileDao, UserProfileDaoEntityFramework>();
container.RegisterType<IUserService, UserService>();
container.RegisterType<ObjectContext, ObjectContext>
(new ContainerControlledLifetimeManager());
<...>
#endregion
„
Resolución de dependencias
tratará ObjectContext como un
singleton
El registro de instancias se haría a través de:
container.RegisterInstance<IGenericType>(concreteInstance)
Unity
Instanciación y configuración del Contedor
„
Configuración a través fichero de configuración: registro de tipos
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
<...>
<unity>
<typeAliases>
<!-- <typeAlias alias="aliasName" type="Class FullName, Assembly Name" /> -->
<typeAlias alias="IUserProfileDAO”
type="Es.Udc.DotNet.MiniPortal.Model.UserProfileDAL.IUserProfileDao, MiniPortal" />
<typeAlias alias="UserProfileDAOEntityFramework"
type="Es.Udc.DotNet.MiniPortal.Model.UserProfileDAL.UserProfileDaoEntityFramework, MiniPortal" />
<typeAlias alias="singleton"
type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity" />
</typeAliases>
<containers>
<container>
<types><type type="IUserProfileDAO" mapTo="UserProfileDAOEntityFramework"></type>
<…>
</container>
</containers>
</unity>
Curso 2008 - 2009
6
Integración de Sistemas
Unity
Instanciación y configuración del Contedor
„
Configuración a través fichero de configuración: creación contenedor
#region Get UserService (Option 3): Configure UserService Injection config file
/*
* We read the UnityConfigurationSection from the default
* configuration file, Web.config, and then populate the
* UnityContainer.
*/
IUnityContainer container = new UnityContainer();
UnityConfigurationSection section =
(UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Containers.Default.Configure(container);
<…>
#endregion
Unity
¿En qué consiste la inyección de dependencias?
Curso 2008 - 2009
„
La inyección de dependencias consiste en la posibilidad
de p
proporcionar
p
((inyectar)
y
) una dependencia
p
externa en
un componente software dado
„
Tipos de Inyección de Dependencias comúnmente
usados en Unity
…
C
Constructor
t t
…
Propiedad
7
Integración de Sistemas
Unity
Inyección de dependencias mediante constructor
D
Dependencia
d
i
public class ObjectContext
{
private String connectionString;
public String ConnectionString { get; private set; }
public ObjectContext(String connectionString) { <...> }
<...>
}
Parámetro, clase, etc. Se
inyecta a través del constructor
Unity
Inyección de dependencias mediante constructor
„
Configuración mediante código
String connectionString = <...>
// Data should be read from configuration file
container.RegisterType<ObjetContexct, ObjectContext>(
new ContainerControlledLifetimeManager());
// Optional: created as singleton
container.Configure<InjectedMembers>()
.ConfigureInjectionFor<ObjectContext>(
new InjectionConstructor(connectionString));
„
Configuración mediante fichero de configuración
<type type="ObjectContext" mapTo="ObjectContext">
<lifetime type="singleton" />
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,
Microsoft.Practices.Unity.Configuration">
<constructor>
<param name="connectionString" parameterType="System.String">
<value value="<...>" />
</param>
</constructor>
</typeConfig>
</type>
Curso 2008 - 2009
8
Integración de Sistemas
Unity
Inyección de dependencias mediante propiedad
namespace Es.Udc.DotNet.MiniPortal.Model.UserService
{
public interface IUserService
{
[Dependency]
IUserProfileDao UserProfileDao { set; }
<...>
}
}
Dependencia se inyecta a
través de una propiedad
Unity
Inyección de dependencias mediante constructor
„
Configuración mediante código
container.RegisterType<IUserProfileDao, UserProfileDaoEntityFramework>();
„
Configuración mediante fichero de configuración
<types>
<!-- ************
Mappings for Bussiness Objects ************* -->
<!-- IUserProfileDAO -->
<type type="IUserProfileDAO" mapTo="UserProfileDAOEntityFramework">
</type>
<!-- IUserService -->
<type type="IUserService" mapTo="UserService">
</type>
</type>
Curso 2008 - 2009
9
Integración de Sistemas
Unity
„
Unity ofrece framework de inversión de control
…
„
Inyección de Dependencias
Ofrece soporte a otros puntos de la Programación
Orientada a Aspectos
…
Intercepción
„
…
Permite interceptar la llamada a un método, analizar los
contenidos de dicha llamada y o bien continuar con la misma
sin modificación o bien modificar su comportamiento.
Intercepción útil para la gestión de transacciones
Unity
Transacciones
„
Estructura típica de un método transaccional
(ver DotNet-Examples-src-1.5)
void RegisterUser(String
g
(
g loginName,
g
, String
g clearPassword,
, UserProfileDetailsVO userProfileDetailsVO)
)
{
<...>
try
{
/* Creates the connection. */ <...>
/* Starts a new transaction. */
DbTransaction transaction =
connection.BeginTransaction(IsolationLevel.Serializable);
<...>
}
catch (...)
{
<...>
}
finally
{
if (rollback)
transaction.Rollback();
else
transaction.Commit();
}
Código idéntico en todos los
casos de uso transaccionales
<...>
}
Curso 2008 - 2009
10
Integración de Sistemas
Unity
Transacciones
„
Soluciones para no repetir código
…
C
Casos
d
de uso iimplementados
l
d a partir
i d
de un P
Procesador
d d
de A
Acciones
i
(DotNet-Examples-src-1.5)
„
Acciones Transaccionales
…
„
Acciones no Transaccionales
…
…
Procesador Acciones crearía entorno transaccional y ejecutaría la acción
Procesador Acciones ejecutaría directamente la acción
Intercepción de métodos transaccionales
„
Etiquetado métodos con atributo [Transactional]
Unity
Transacciones
„
Creación atributo
namespace Es.Udc.DotNet.ModelUtil.Transactions
{
public class TransactionalAttribute : HandlerAttribute
{
public override ICallHandler CreateHandler(
IUnityContainer container)
{
return new TransactionalHandler();
}
}
}
„
Uso:
[Transactional]
LoginResult Login(String loginName, String password,
Boolean passwordIsEncrypted);
Curso 2008 - 2009
11
Integración de Sistemas
Unity
Transacciones
„
Creación interceptor (handler)
public class TransactionalHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input,
GetNextHandlerDelegate getNext)
{
IMethodReturn result;
using (TransactionScope transaction = new TransactionScope())
{
result = getNext()(input, getNext);
Creación entorno
transaccional
transaction.Complete();
}
return result;
}
}
Llamada al método
mediante delegado
}
Unity
Transacciones
„
Configuración para el uso de la intercepción en Unity
<extensions>
<add type="Microsoft.Practices.Unity.InterceptionExtension.Interception,
Microsoft.Practices.Unity.Interception" />
</extensions>
<!-- Interception schema for transactional methods -->
<extensionConfig>
<add name
name="TransactionalIntercepcion"
TransactionalIntercepcion
type=“<...>">
<interceptors>
<interceptor type="InterfaceInterceptor">
<key type="IUserService" />
</interceptor>
</interceptors>
</add>
Interfaz que será
</extensionConfig>
Curso 2008 - 2009
interceptada
12
Integración de Sistemas
Unity
Transacciones
„
Configuración para el uso de la intercepción en Unity
container.RegisterType<IUserService, UserService>();
container.AddNewExtension<Interception>();
container.Configure<Interception>().
SetDefaultInterceptorFor<IUserService>(
new InterfaceInterceptor());
Curso 2008 - 2009
13

Documentos relacionados