Création d’un résolveur personnalisé avec un conteneur Unity
Vous pouvez créer un programme de résolution personnalisé à l’aide du bloc d’application Unity (Unity) (https://go.microsoft.com/fwlink/?LinkId=188286) pour l’injection de dépendances au moment de l’exécution de sources de logique de résolution et de métadonnées.
Fournisseurs de faits
Les fournisseurs de faits sont des instances de classes qui implémentent l’interface IFactProvider . Cette interface expose trois surcharges différentes d’une méthode nommée RegisterFact. Cette méthode prend le message, la configuration du programme de résolution et, dans certains cas, le contexte de pipeline, et retourne un objet . Cet objet peut être des informations extraites des entrées d’une certaine manière, il peut s’agir d’un calcul d’une certaine forme ou d’une recherche à partir d’une source externe. Chaque objet retourné par un fournisseur de faits peut être appelé fait et est généralement ajouté à une liste par le conteneur de résolution pour une utilisation ultérieure par un traducteur de faits.
Un programme de résolution Unity peut avoir zéro ou plusieurs fournisseurs de faits qui peuvent être ajoutés ou supprimés à tout moment avec une seule modification de configuration.
Le code suivant est un exemple de la logique contenue dans un fournisseur de faits. Ce code se trouve également dans le fichier ItineraryStaticFactProvider.cs de l’ESB. Projet Resolver.Itinerary.Facts. Il s’agit d’un composant du programme de résolution ITINERARY-STATIC qui collecte le nom et la version d’un itinéraire à partir du chaîne de connexion du programme de résolution.
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;
}
Traducteurs de faits
Les traducteurs de faits sont des instances de classes qui implémentent l’interface IFactTranslator . Cette interface expose une méthode unique nommée TranslateFact. Cette méthode accepte un tableau d’objets qui contient une liste de faits et le dictionnaire de résolution qui sera retourné par la suite par le programme de résolution à l’aide du traducteur de faits. Un traducteur de faits est chargé de traiter les faits fournis par les fournisseurs de faits de manière significative, puis de remplir le dictionnaire de résolution.
Un programme de résolution Unity peut avoir zéro ou plusieurs traducteurs de faits qui peuvent être ajoutés ou supprimés à tout moment avec une seule modification de configuration.
Le code suivant est un exemple de la logique contenue dans un traducteur de faits. Ce code se trouve également dans le fichier ItineraryStaticFactTranslator.cs de l’ESB. Projet Resolver.Itinerary.Facts. Il s’agit d’un composant du programme de résolution ITINERARY-STATIC qui effectue une requête de base de données pour collecter le xml d’itinéraire d’un itinéraire par nom et, éventuellement, par version.
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
Résoudre les conteneurs
Un conteneur resolve est une classe qui implémente l’interface IResolveContainer . En règle générale, il implémente également l’interface IResolveProvider . L’interface IResolveContainer expose une méthode unique nommée Initialize qui accepte un IUnityContainer. Le conteneur passé à cette méthode contient toutes les dépendances (c’est-à-dire les instances des classes IFactProvider et IFactTranslator, et tous les autres types requis) nécessaires au programme de résolution pour terminer son traitement.
Le code suivant est un exemple d’implémentation de l’interface IResolveContainer . Ce code se trouve également dans le fichier StaticItineraryResolveContainer.cs de l’ESB. Projet Resolver.Itinerary.
#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
Dans un conteneur de résolution, dans les implémentations des méthodes Resolve à partir de l’interface IResolveProvider , il est nécessaire d’itérer au sein de tous les fournisseurs de faits et traducteurs de faits dans le conteneur Unity pour permettre à chacun d’entre eux d’effectuer leur traitement.
Le code suivant est un exemple de la logique contenue dans un conteneur Resolve. Ce code se trouve également dans le fichier StaticItineraryResolveContainer.cs de l’ESB. Projet Resolver.Itinerary.
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;
}
}
Configuration d’un programme de résolution Unity personnalisé
Pour configurer un programme de résolution Unity personnalisé, les mêmes étapes de configuration s’appliquent que lors de la création d’un programme de résolution personnalisé ; Toutefois, il existe une configuration supplémentaire qui doit être incluse pour inscrire correctement les composants qui composent le programme de résolution.
Tout d’abord, dans le fichier Esb.config, sous la déclaration du programme de résolution, un nœud resolverConfig doit être ajouté avec les deux propriétés suivantes :
unitySectionName. Cette propriété contient le nom de la section de configuration dans le fichier de configuration qui contient la configuration du bloc d’application Unity ; par défaut, la valeur de cette propriété est esb.resolver.
unityContainerName. Cette propriété contient le nom du conteneur Unity défini dans la configuration Unity spécifique à votre programme de résolution personnalisé.
Le code XML suivant est un exemple de configuration nécessaire dans le nœud des résolveurs .
<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>
Le code XML suivant est un exemple de configuration nécessaire sous le nœud 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>
Pour plus d’informations sur la configuration nécessaire dans le nœud esb.resolvers , consultez Schéma source pour le bloc d’application Unity (https://go.microsoft.com/fwlink/?LinkId=188288) sur MSDN.
Création d’un programme de résolution Unity personnalisé
Pour créer un programme de résolution Unity personnalisé
(Facultatif) Créez un ou plusieurs assemblys avec une classe qui implémente l’interface IFactProvider et contient une méthode RegisterFact qui fournit les informations nécessaires à la résolution.
(Facultatif) Créez un ou plusieurs assemblys avec une classe qui implémente l’interface IFactTranslator et contient une méthode TranslateFact qui traduit les faits fournis en paires clé/valeur dans le dictionnaire du programme de résolution.
Créez un assembly avec une classe qui implémente l’interface IResolveContainer et IResolveProvider et qui contient une méthode Resolve qui valide la configuration du programme de résolution, rassemble tous les faits des fournisseurs de faits, effectue tout traitement spécialisé, les traduit à l’aide des traducteurs de faits et retourne les faits traduits en tant que instance de la classe Dictionary.
Inscrivez le programme de résolution en l’ajoutant au fichier de configuration Esb.config à l’aide d’un <élément de programme de résolution> qui contient le moniker racine en tant qu’attribut name et le nom d’assembly complet comme attribut de type .
Ajoutez la configuration spécifique à Unity au fichier Esb.config pour ce programme de résolution.
(Facultatif) Créez un schéma qui définit le moniker racine et les paramètres de requête, puis enregistrez-le dans l’ESB. Dossier Schemas.Resolvers. Le nom doit suivre les conventions de nommage ESB existantes ; Cela signifie qu’il doit utiliser le nom du moniker racine ajouté à « _Resolution.xsd ».
(Facultatif) Générez une classe à partir du nouveau schéma et enregistrez-la dans l’assembly de programme de résolution personnalisé. Cela expose les paramètres typés dans le programme de résolution personnalisé.
Inscrivez tous les assemblys dans le Global Assembly Cache.