Unity コンテナーでカスタム リゾルバーを作成する
Unity アプリケーション ブロック (Unity) (https://go.microsoft.com/fwlink/?LinkId=188286) を使用して、解決ロジックとメタデータ ソースの実行時の依存関係の挿入用にカスタム リゾルバーを作成できます。
ファクト プロバイダー
ファクト プロバイダーは、 IFactProvider インターフェイスを実装するクラスのインスタンスです。 このインターフェイスは、 RegisterFact という名前のメソッドの 3 つの異なるオーバーロードを公開します。 このメソッドは、メッセージ、リゾルバー構成、場合によってはパイプライン コンテキストを受け取り、オブジェクトを返します。 このオブジェクトは、何らかの方法で入力から抽出された情報であってもよいし、何らかの形式の計算であってもよいし、何らかの外部ソースから検索してもよい。 ファクト プロバイダーによって返される各オブジェクトはファクトと呼ばれ、通常はファクト トランスレーターによって後で使用するために解決コンテナーによってリストに追加されます。
Unity リゾルバーには、1 つの構成変更でいつでも追加または削除できるファクト プロバイダーが 0 個以上存在する場合があります。
次のコードは、ファクト プロバイダーに含まれるロジックの例です。 このコードは、ESB の ItineraryStaticFactProvider.cs ファイルでも確認できます。Resolver.Itinerary.Facts プロジェクト。 これは、リゾルバー 接続文字列から旅程の名前とバージョンを収集する ITINERARY-STATIC リゾルバーのコンポーネントです。
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;
}
ファクト トランスレーター
ファクト トランスレーターは、 IFactTranslator インターフェイスを実装するクラスのインスタンスです。 このインターフェイスは 、TranslateFact という名前の 1 つのメソッドを公開します。 このメソッドは、ファクトの一覧と、ファクト トランスレーターを使用してリゾルバーによって後で返されるリゾルバー ディクショナリを含むオブジェクト配列を受け取ります。 ファクト トランスレーターは、ファクト プロバイダーから提供されたファクトを意味のある方法で処理し、リゾルバー ディクショナリにデータを入力する役割を担います。
Unity リゾルバーには、1 つの構成変更でいつでも追加または削除できるファクト トランスレーターが 0 個以上存在する場合があります。
次のコードは、ファクト トランスレーターに含まれるロジックの例です。 このコードは、ESB の ItineraryStaticFactTranslator.cs ファイルでも確認できます。Resolver.Itinerary.Facts プロジェクト。 これは ITINERARY-STATIC リゾルバー内のコンポーネントであり、データベース クエリを実行して、名前によってスケジュールのスケジュール XML を収集し、必要に応じてバージョン別にスケジュール XML を収集します。
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
コンテナーを解決する
解決コンテナーは、 IResolveContainer インターフェイスを実装するクラスです。 通常は、 IResolveProvider インターフェイスも実装します。 IResolveContainer インターフェイスは、IUnityContainer を受け取る Initialize という名前の 1 つのメソッドを公開します。 このメソッドに渡されるコンテナーには、リゾルバーが処理を完了するために必要なすべての依存関係 (つまり、 クラス IFactProvider と IFactTranslator のインスタンス、および必要なその他の型) が含まれます。
次のコードは、 IResolveContainer インターフェイスの実装の例です。 このコードは、ESB の StaticItineraryResolveContainer.cs ファイルでも確認できます。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
解決コンテナーでは、IResolveProvider インターフェイスからの Resolve メソッドの実装では、Unity コンテナー内のすべてのファクト プロバイダーとファクト トランスレーターを反復処理して、それぞれの処理を実行できるようにする必要があります。
次のコードは、Resolve コンテナーに含まれるロジックの例です。 このコードは、ESB の StaticItineraryResolveContainer.cs ファイルでも確認できます。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;
}
}
カスタム Unity リゾルバーの構成
カスタム Unity リゾルバーを構成するには、カスタム リゾルバーの作成時と同じ構成手順が適用されます。ただし、リゾルバーを構成するコンポーネントを適切に登録するために含める必要がある追加の構成がいくつかあります。
まず、Esb.config ファイルの競合回避モジュール宣言の下に、次の 2 つのプロパティを含む resolverConfig ノードを追加する必要があります。
unitySectionName。 このプロパティには、Unity アプリケーション ブロックの構成を含む構成ファイルの構成セクションの名前が含まれています。既定では、このプロパティの値は esb.resolver です。
unityContainerName。 このプロパティには、カスタム リゾルバーに固有の Unity 構成で定義されている Unity コンテナーの名前が含まれます。
次の XML は、 リゾルバー ノードで必要な構成の例です。
<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>
次の XML は、 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>
esb.resolvers ノードで必要な構成の詳細については、MSDN の Unity アプリケーション ブロック (https://go.microsoft.com/fwlink/?LinkId=188288) のソース スキーマに関するページを参照してください。
カスタム Unity リゾルバーの作成
カスタム Unity リゾルバーを作成するには
(省略可能) IFactProvider インターフェイスを実装し、解決に必要な情報を提供する RegisterFact メソッドを含むクラスを使用して、アセンブリまたはアセンブリを作成します。
(省略可能) IFactTranslator インターフェイスを実装し、指定されたファクトをリゾルバー ディクショナリ内のキーと値のペアに変換する TranslateFact メソッドを含むクラスを使用して、アセンブリまたはアセンブリを作成します。
IResolveContainer インターフェイスと IResolveProvider インターフェイスを実装し、リゾルバーの構成を検証し、ファクト プロバイダーからすべてのファクトを収集し、特殊な処理を実行し、ファクト トランスレーターを使用して変換し、変換されたファクトを Dictionary クラスのインスタンスとして返す Resolve メソッドを含むクラスを使用してアセンブリを作成します。
ルート モニカーを name 属性として、完全修飾アセンブリ名を型属性として含むリゾルバー要素を使用して<、リゾルバー>を Esb.config 構成ファイルに追加して、リゾルバーを登録します。
このリゾルバーの Esb.config ファイルに Unity 固有の構成を追加します。
(省略可能)ルート モニカーとクエリ パラメーターを定義するスキーマを作成し、ESB に保存します。Schemas.Resolvers フォルダー。 名前は、既存の ESB 名前付け規則に従う必要があります。これは、"_Resolution.xsd" を付加したルート モニカーの名前を使用する必要があることを意味します。
(省略可能)新しいスキーマからクラスを生成し、カスタム リゾルバー アセンブリに保存します。 これにより、カスタム リゾルバーで型指定されたパラメーターが公開されます。
すべてのアセンブリをグローバル アセンブリ キャッシュに登録します。