Creación de un solucionador personalizado con un contenedor de Unity
Puede crear un solucionador personalizado mediante el bloque de aplicaciones de Unity (Unity) (https://go.microsoft.com/fwlink/?LinkId=188286) para la inserción de dependencias en tiempo de ejecución de la lógica de resolución y los orígenes de metadatos.
Proveedores de hechos
Los proveedores de hechos son instancias de clases que implementan la interfaz IFactProvider . Esta interfaz expone tres sobrecargas diferentes de un método denominado RegisterFact. Este método toma el mensaje, la configuración del solucionador y, en algunos casos, el contexto de canalización y devuelve un objeto . Este objeto puede ser información extraída de las entradas de alguna manera, puede ser un cálculo de algún formulario o se puede buscar desde algún origen externo. Cada objeto devuelto por un proveedor de hechos se puede denominar hecho y, normalmente, el contenedor de resolución lo agrega a una lista para su uso posterior por un traductor de hechos.
Un solucionador de Unity puede tener cero o más proveedores de hechos que se pueden agregar o quitar en cualquier momento con un único cambio de configuración.
El código siguiente es un ejemplo de la lógica contenida en un proveedor de hechos. Este código también se puede encontrar en el archivo ItineraryStaticFactProvider.cs del ESB. Proyecto Resolver.Itinerary.Facts. Es un componente de la resolución ITINERARY-STATIC que recopila el nombre y la versión de un itinerario del solucionador cadena de conexión.
public object RegisterFact(IBaseMessage message, IPipelineContext pipelineContext, Dictionary\<string, string\> resolverContents)
{
return GetItineraryFactFromResolver(resolverContents);
}
private static object GetItineraryFactFromResolver(Dictionary\<string, string\> resolverContents)
{
if (resolverContents == null)
throw new ArgumentNullException("resolverContents");
ItineraryFact itineraryFact = new ItineraryFact();
itineraryFact.Name = ResolverMgr.GetConfigValue(resolverContents, true, "name");
string version = ResolverMgr.GetConfigValue(resolverContents, false, "version");
if (!string.IsNullOrEmpty(version))
{
EventLogger.Write(string.Format("Version set with value {0}.", version));
itineraryFact.SetVersion(version);
}
return itineraryFact;
}
Traductores de hechos
Los traductores de hechos son instancias de clases que implementan la interfaz IFactTranslator . Esta interfaz expone un único método denominado TranslateFact. Este método toma una matriz de objetos que contiene una lista de hechos y el diccionario del solucionador que el solucionador devolverá más adelante mediante el traductor de hechos. Un traductor de hechos es responsable de procesar los hechos proporcionados por los proveedores de hechos de forma significativa y, a continuación, rellenar el diccionario del solucionador.
Un solucionador de Unity puede tener cero o más traductores de hechos que se pueden agregar o quitar en cualquier momento con un único cambio de configuración.
El código siguiente es un ejemplo de la lógica contenida en un traductor de hechos. Este código también se puede encontrar en el archivo ItineraryStaticFactTranslator.cs del ESB. Proyecto Resolver.Itinerary.Facts. Es un componente de la resolución ITINERARY-STATIC que realiza una consulta de base de datos para recopilar el XML del itinerario para un itinerario por nombre y, opcionalmente, por versión.
public void TranslateFact(object[] facts, Dictionary\<string, string\> factDictionary)
{
#region Argument Check
if (null == facts) throw new ArgumentNullException("fact");
if (null == factDictionary) throw new ArgumentNullException("factDictionary");
#endregion
#region Local Variables
Version version = new Version(1, 0);
#endregion
try
{
foreach (object fact in facts)
{
if (fact is ItineraryFact)
{
ItineraryFact targetFact = (ItineraryFact)fact;
factDictionary.Add(_FactKeyItineraryName, targetFact.Name ?? string.Empty);
if (null != targetFact.Version)
{
factDictionary.Add(_FactKeyItineraryVersion, targetFact.Version.ToString(2) ?? string.Empty);
version = targetFact.Version;
}
string xml = null;
if (targetFact.Version != null)
{
xml = _repositoryProvider.GetItinerary(targetFact.Name, version.Major, version.Minor);
}
else
{
xml = _repositoryProvider.GetItinerary(targetFact.Name);
}
if (!string.IsNullOrEmpty(xml))
{
factDictionary.Add(_FactKeyItinerary, xml);
}
break;
}
}
}
#region Exception Handling
catch (System.Exception)
{
throw;
}
#endregion
}
#endregion
Resolución de contenedores
Un contenedor de resolución es una clase que implementa la interfaz IResolveContainer . Normalmente, también implementa la interfaz IResolveProvider . La interfaz IResolveContainer expone un único método denominado Initialize que toma un IUnityContainer. El contenedor pasado a este método contendrá todas las dependencias (es decir, instancias de las clases IFactProvider e IFactTranslator, y cualquier otro tipo necesario) necesaria para que el solucionador complete su procesamiento.
El código siguiente es un ejemplo de una implementación de la interfaz IResolveContainer . Este código también se puede encontrar en el archivo StaticItineraryResolveContainer.cs del ESB. Proyecto Resolver.Itinerario.
#region IResolveContainer Members
private static IUnityContainer Container;
// <summary>
// This is used by the Unity resolver to initialize the current
// object with the Unity container.
// </summary>
// <param name="container">Unity container used for dependency
// injection.</param>
// <remarks>
// The container used is the ITINERARY container, although this is
// configurable in Esb.config.
// </remarks>
public void Initialize(IUnityContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
Container = container;
}
#endregion
En un contenedor de resolución, en las implementaciones de los métodos Resolve de la interfaz IResolveProvider , es necesario recorrer en iteración todos los proveedores de hechos y los traductores de hechos del contenedor de Unity para permitir que cada uno de ellos realice su procesamiento.
El código siguiente es un ejemplo de la lógica contenida en un contenedor Resolve. Este código también se puede encontrar en el archivo StaticItineraryResolveContainer.cs del ESB. Proyecto Resolver.Itinerario.
public Dictionary\<string, string\> Resolve(ResolverInfo resolverInfo,
XLANGMessage message)
{
#region Argument Check
if (String.IsNullOrEmpty(resolverInfo.Config))
throw new ArgumentNullException("resolverInfo.Config");
if (String.IsNullOrEmpty(resolverInfo.Resolver))
throw new ArgumentNullException("resolverInfo.Resolver");
if (null == message)
throw new ArgumentNullException("message");
#endregion Argument Check
return ResolveStatic(resolverInfo.Config, resolverInfo.Resolver,
(factProvider, resolverContent) =>
factProvider.RegisterFact(message, resolverContent)
);
}
private Dictionary\<string, string\> ResolveStatic(string config, string resolver,
Func<IFactProvider, Dictionary\<string, string\>, object> RegisterFact)
{
try
{
EventLogger.Write(string.Format("Received {0} value in ITINERARY STATIC resolver.", config));
Dictionary\<string, string\> queryParams =
ResolverMgr.GetFacts(config, resolver);
List<object> facts = new List<object>();
foreach (IFactProvider factProvider in Container.ResolveAll<IFactProvider>())
{
facts.Add(RegisterFact(factProvider, queryParams));
}
Dictionary\<string, string\> resolverDictionary = new Dictionary\<string, string\>();
object[] convertedFacts = facts.ToArray();
foreach (IFactTranslator translator in Container.ResolveAll<IFactTranslator>())
{
translator.TranslateFact(convertedFacts, resolverDictionary);
}
return resolverDictionary;
}
catch (System.Exception ex)
{
EventLogger.Write(MethodInfo.GetCurrentMethod(), ex);
throw;
}
}
Configuración de un solucionador de Unity personalizado
Para configurar un solucionador de Unity personalizado, se aplican los mismos pasos de configuración que al crear una resolución personalizada; sin embargo, hay alguna configuración adicional que se debe incluir para registrar correctamente los componentes que componen la resolución.
En primer lugar, en el archivo Esb.config, en la declaración del solucionador, se debe agregar un nodo resolverConfig con las dos propiedades siguientes:
unitySectionName. Esta propiedad contiene el nombre de la sección de configuración del archivo de configuración que contiene la configuración del bloque de aplicación de Unity; De forma predeterminada, el valor de esta propiedad esb.resolver.
unityContainerName. Esta propiedad contiene el nombre del contenedor de Unity definido en la configuración de Unity específica de la resolución personalizada.
El siguiente XML es un ejemplo de la configuración necesaria en el nodo de resolución .
<resolver name="ITINERARY-STATIC" type="Microsoft.Practices.ESB.Resolver.Unity.ResolveProvider, Microsoft.Practices.ESB.Resolver.Unity, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22">
<resolverConfig>
<add name="unitySectionName" value="esb.resolver" />
<add name="unityContainerName" value="ITINERARY" />
</resolverConfig>
</resolver>
El siguiente XML es un ejemplo de la configuración necesaria en el nodo esb.resolver .
<typeAliases>
<!-- Lifetime manager types -->
<typeAlias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<!-- std type providers -->
<typeAlias alias="string" type="System.String, mscorlib"/>
<typeAlias alias="int" type="System.Int32, mscorlib"/>
<!-- repository providers -->
<typeAlias alias="IRepositoryProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.Facts.Repository.IRepositoryProvider, Microsoft.Practices.ESB.Resolver.Itinerary.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="SqlRepositoryProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.DataAccess.SqlRepositoryProvider, Microsoft.Practices.ESB.Resolver.Itinerary.DataAccess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<!-- fact providers -->
<typeAlias alias="IFactProvider" type="Microsoft.Practices.ESB.Resolver.Facts.IFactProvider, Microsoft.Practices.ESB.Resolver.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="IFactTranslator" type="Microsoft.Practices.ESB.Resolver.Facts.IFactTranslator, Microsoft.Practices.ESB.Resolver.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="ItineraryFactProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.Facts.ItineraryFactProvider, Microsoft.Practices.ESB.Resolver.Itinerary.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="ItineraryStaticFactProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.Facts.ItineraryStaticFactProvider, Microsoft.Practices.ESB.Resolver.Itinerary.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="ItineraryHeaderFactProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.Facts.ItineraryHeaderFactProvider, Microsoft.Practices.ESB.Resolver.Itinerary.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="ResolutionFactProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.Facts.ResolutionFactProvider, Microsoft.Practices.ESB.Resolver.Itinerary.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="DefaultFactTranslator" type="Microsoft.Practices.ESB.Resolver.Facts.DefaultFactTranslator, Microsoft.Practices.ESB.Resolver.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="ItineraryFactTranslator" type="Microsoft.Practices.ESB.Resolver.Itinerary.Facts.ItineraryFactTranslator, Microsoft.Practices.ESB.Resolver.Itinerary.Facts, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<!-- resolve providers -->
<typeAlias alias="IResolveProvider" type="Microsoft.Practices.ESB.Resolver.IResolveProvider, Microsoft.Practices.ESB.Resolver, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22"/>
<typeAlias alias="ItineraryResolveProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.BREItineraryResolverContainer,Microsoft.Practices.ESB.Resolver.Itinerary, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22 "/>
<typeAlias alias="StaticItineraryResolveProvider" type="Microsoft.Practices.ESB.Resolver.Itinerary.StaticItineraryResolveContainer,Microsoft.Practices.ESB.Resolver.Itinerary, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c62dd63c784d6e22 "/>
</typeAliases>
<containers>
<container name="ITINERARY">
<types>
<type type="IResolveProvider" mapTo="StaticItineraryResolveProvider" />
<type type="IRepositoryProvider" mapTo="SqlRepositoryProvider" name="CurrentRepositoryProvider">
<lifetime type="singleton" />
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<constructor>
<param name="connectionStringName" parameterType="string">
<value value="ItineraryDb"/>
</param>
<param name="cacheManagerName" parameterType="string">
<value value="Itinerary Cache Manager"/>
</param>
<param name="cacheTimeout" parameterType="string">
<value value="120" />
</param>
</constructor>
</typeConfig>
</type>
<type type="IFactProvider" mapTo="ResolutionFactProvider" name="ResolutionFactProvider" />
<type type="IFactProvider" mapTo="ItineraryHeaderFactProvider" name="HeaderFactProvider" />
<type type="IFactProvider" mapTo="ItineraryStaticFactProvider" name="StaticFactProvider" />
<type type="IFactTranslator" mapTo="DefaultFactTranslator" name="DefaultFactTranslator">
<lifetime type="singleton" />
</type>
<type type="IFactTranslator" mapTo="ItineraryFactTranslator" name="ItineraryFactTranslator">
<lifetime type="singleton" />
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement,Microsoft.Practices.Unity.Configuration, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<constructor>
<param name="repositoryProvider" parameterType="IRepositoryProvider">
<dependency name="CurrentRepositoryProvider"/>
</param>
</constructor>
</typeConfig>
</type>
</types>
</container>
</containers>
Para obtener información detallada sobre la configuración necesaria en el nodo esb.resolvers , vea Source Schema for the Unity Application Block (https://go.microsoft.com/fwlink/?LinkId=188288) en MSDN.
Creación de un solucionador de Unity personalizado
Para crear una resolución personalizada de Unity
(Opcional) Cree un ensamblado o ensamblado con una clase que implemente la interfaz IFactProvider y contenga un método RegisterFact que proporcione información necesaria para que se produzca la resolución.
(Opcional) Cree un ensamblado o ensamblados con una clase que implemente la interfaz IFactTranslator y contenga un método TranslateFact que traduzca los hechos proporcionados a pares clave-valor dentro del diccionario del solucionador.
Cree un ensamblado con una clase que implemente la interfaz IResolveContainer e IResolveProvider y que contiene un método Resolve que valida la configuración del solucionador, recopila todos los hechos de los proveedores de hechos, realiza cualquier procesamiento especializado, los traduce mediante los traductores de hechos y devuelve los hechos traducidos como una instancia de la clase Dictionary .
Registre el solucionador agregándolo al archivo de configuración de Esb.config mediante un <elemento de resolución> que contenga el moniker raíz como atributo name y el nombre completo del ensamblado como atributo de tipo .
Agregue la configuración específica de Unity al archivo Esb.config para esta resolución.
(Opcional) Cree un esquema que defina el moniker raíz y los parámetros de consulta y guárdelo en el ESB. Carpeta Schemas.Resolvers. El nombre debe seguir las convenciones de nomenclatura de ESB existentes; esto significa que debe usar el nombre del moniker raíz anexado con "_Resolution.xsd".
(Opcional) Genere una clase a partir del nuevo esquema y guárdela en el ensamblado de resolución personalizado. Esto expondrá los parámetros con tipo en la resolución personalizada.
Registre todos los ensamblados en la caché global de ensamblados.