Microsoft Object Builder

みなさんこんにちは! これはHabréでの私の最初の記事です。 今日、SpringおよびTapestry Javaフレームワークの説明のフィードに直面して、Habraを調べて、Microsoftの「競合する」フレームワーク、特にComposite UI Application Block(CAB)とUnityの鑑定家を見つけることにしました。 驚いたことに、何も見つかりませんでした。 Javaフレームワークに関する記事のコメントで、依存性注入メカニズムを説明する要求を見たので、IoCの問題の説明から.Netフレームワークに関する一連の記事を開始することにしました。 素晴らしいCABエンジンの基礎(過去)-Microsoft Object Builderです。

それは何であり、どこで使用されています


Object Builder(以降OBと呼びます)は、多くの依存オブジェクトを暗黙的にリンクグラフに合成するためのメカニズムです。 OBは、2005年5月に、デスクトップアプリケーションフレームワークであるCAB (またはSmartClient)と連携したオープンソースのパターンとプラクティスを備えた「複雑なプロジェクト」の偽造を通じてMicrosoftから提供されました。 基本的なCABクラスのセットは、ユーザーがエンジンオブジェクト(ユーザーコントロール、サービス、拡張ロケーションなど)を作成するときに、OBを依存性注入メカニズムとして使用します。

自分を置く方法


ここからCABをダウンロードして配置します。 インストーラーは3つのアセンブリをGACに追加します。そのうちの1つはOBです。

Object Builderの構成要素とその仕組み


基本的に、OBはいくつかのプログラミングパターンの集合です。 構造について簡単に説明します。



魂には例が必要です! 例として、オブジェクトを作成しますIProgramServiceマイクロサービス:
interface IProgramService
{
void DoWork();
}


* This source code was highlighted with Source Code Highlighter .

そして、その実装は次のとおりです。
class ProgramService : IProgramService
{
#region IProgramService Members

public void DoWork()
{
Console .WriteLine( string .Format( "[{0}] Program Service: DoWork()" , _guid));
}

#endregion

private Guid _guid = Guid .NewGuid();
public Guid Guid
{
get { return _guid; }
}
}


* This source code was highlighted with Source Code Highlighter .

作成コードは次のようになります。
Builder builder = new Builder();
Locator locator = new Locator();
IProgramService service = builder.BuildUp<ProgramService>(locator, null , null );

service.DoWork();


* This source code was highlighted with Source Code Highlighter .

とても簡単です。

次に、依存性注入戦略を検討します。

申込み


ビルダーを作成するためのコードを見ると、重要な戦略がどのように追加されているかがわかります。

public Builder(IBuilderConfigurator<BuilderStage> configurator)
{
Strategies.AddNew<TypeMappingStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<SingletonStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<ConstructorReflectionStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<PropertyReflectionStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<MethodReflectionStrategy>(BuilderStage.PreCreation);
Strategies.AddNew<CreationStrategy>(BuilderStage.Creation);
Strategies.AddNew<PropertySetterStrategy>(BuilderStage.Initialization);
Strategies.AddNew<MethodExecutionStrategy>(BuilderStage.Initialization);
Strategies.AddNew<BuilderAwareStrategy>(BuilderStage.PostInitialization);

Policies.SetDefault<ICreationPolicy>( new DefaultCreationPolicy());

if (configurator != null )
configurator.ApplyConfiguration( this );
}


* This source code was highlighted with Source Code Highlighter .


依存関係間の関係を作成するために使用できる方法と、これらの戦略の仕組みを理解しましょう。

TypeMappingStrategy (PreCreation)-タイプ一致ポリシー。 たとえば、最後の例では、作成するタイプを明示的に示しました。 しかし、毎回どのクラスがIProgramServiceインターフェイスを実装するかを表示したくない場合はどうでしょうか? IProgramServiceを作成し、誰が特定のタイプになるのかを知りたくない場合は、プログラマーVasyaにそれを傷つけさせてください。 ITypeMappingPolicyを作成するポリシーを使用します。 このポリシーは、インターフェイスと特定のタイプの間の対応をロケーターに伝えます。

class TypeMappingPolicy : ITypeMappingPolicy
{
#region ITypeMappingPolicy Members

public DependencyResolutionLocatorKey Map(DependencyResolutionLocatorKey incomingTypeIDPair)
{
return new DependencyResolutionLocatorKey( typeof (ProgramService), null );
}

#endregion
}


* This source code was highlighted with Source Code Highlighter .


ポリシーの登録は次の方法で行われます。
builder.Policies.Set<ITypeMappingPolicy>( new TypeMappingPolicy(), typeof (IProgramService), null );
IProgramService service = builder.BuildUp<IProgramService>(locator, null , null );


* This source code was highlighted with Source Code Highlighter .


SingletonStrategy (PreCreation)-シングルトンとしてオブジェクトを作成するための戦略。 これは、指定されたタイプの作成されたオブジェクトが一度だけ作成されることを意味します。 このタイプを作成する以降のすべての試行は、既存のオブジェクトの置換によって置き換えられます。 これを行うには、作成されるタイプを特別なキーで明示的にマークする必要があります。 DependencyResolutionLocatorKey
IProgramService service = builder.BuildUp<ProgramService>(locator, null , null );
DependencyResolutionLocatorKey key = new DependencyResolutionLocatorKey( typeof (ProgramService), null );
locator.Add(key, service);

IProgramService service2 = builder.BuildUp<ProgramService>(locator, null , null );


* This source code was highlighted with Source Code Highlighter .

この場合、 serviceservice2は同じオブジェクトを指します。

ConstructorReflectionStrategy (PreCreation)- コンストラクターを介してオブジェクトを作成するための戦略。 名前はそれ自体を表しています-戦略は[InjectionConstructor]属性でマークされたオブジェクトのコンストラクターを選択し、 [Dependency]属性でマークされた各パラメーターに対してロケーターを介してそれを見つけます。 次に、コンストラクターが呼び出され、そこに落ち着いたパラメーターを渡します。
[InjectionConstructor]
public ServiceConsumer([Dependency]IProgramService service)
{
_service = service;
}


* This source code was highlighted with Source Code Highlighter .

パラメーターを挿入する方法はいくつかあります。 Dependency属性のプロパティを使用して、作成するタイプを指定したり、目的のタイプが見つからない場合の動作を決定したりできます。 たとえば、新しいものを作成する( CreateNew )か、例外をスローします。
[InjectionConstructor]
public ServiceConsumer(
[Dependency(CreateType= typeof (ProgramService), NotPresentBehavior=NotPresentBehavior.Throw)]IProgramService service)
{
_service = service;
}


* This source code was highlighted with Source Code Highlighter .

言うまでもなく、別のオブジェクトに依存する1つのオブジェクトを作成する場合、他のオブジェクトはロケーターで解決する必要があります。
IProgramService service = builder.BuildUp<ProgramService>(locator, null , null );
DependencyResolutionLocatorKey key = new DependencyResolutionLocatorKey( typeof (IProgramService), null );
locator.Add(key, service);

ServiceConsumer consumer = builder.BuildUp<ServiceConsumer>(locator, null , null );


* This source code was highlighted with Source Code Highlighter .


CreationStrategy (Creation)は、一般的な作成戦略です。 上記の最初の例では、オブジェクトは作成戦略によって正確に構築されます。 最初に、戦略はICreationPolicyを構築するためのカスタムポリシーを検索し、ポリシーが見つからない場合は、「ネイティブ」ポリシーを使用します。 ネイティブ作成ポリシーは、(リフレクションを介して)オブジェクトの最初のコンストラクターを決定し、コンストラクター内の各依存関係(パラメーター)の構築チェーンを開始するようビルダーに指示します。 次に、 Activatorを介して実行します。 この戦略の特徴は、すでに作成されたオブジェクトをそこに転送できることです。 それから、戦略は何もしません:)それは単に、 Creation隣にStageがある他の戦略に制御を移します。 もう一度最後になりますが、言い換えれば、 new()を介してオブジェクトを作成し、それをビルダーに渡すことができます。 この場合、ビルダーはオブジェクトを作成せず、単に依存関係をオブジェクトに挿入します。

PropertyReflectionStrategy + PropertySetterStrategy (初期化)。 オブジェクトのプロパティに依存関係を挿入できる戦略(実際、意味的には、これは1つの戦略です)。 要するに、この作業-PropertyReflectionStrategyは、 [Dependency]属性でマークされたオブジェクトのプロパティを定義し、そこに挿入する必要があるオブジェクトのタイプを認識し、この情報をリストするIPropertySetterPolicyポリシーを作成します。 さらに、チェーンに続いて、 PropertySetterStrategyが動作を開始します。これにより、ポリシーが検索され、そこから挿入する必要があるプロパティが決定され、オブジェクトが解決され、適切な場所に設定されます。 ユーザーがIPropertySetterPolicyを使用できるように、戦略分割チップがここにあります。
[Dependency(CreateType= typeof (ProgramService),
NotPresentBehavior=NotPresentBehavior.CreateNew)]
public IProgramService ProgramService
{
set { _service = value ; }
get { return _service; }
}


* This source code was highlighted with Source Code Highlighter .


このコードは簡単に書き直すことができます。
[CreateNew]
public ProgramService ProgramService2
{
set { _service = value ; }
}


* This source code was highlighted with Source Code Highlighter .


MethodReflectionStrategy + MethodExecutionStrategy (初期化)。 本質的に、これらの2つの戦略は、 Property依存性戦略と同型です。 のみ、プロパティを設定する代わりに、 [InjectionMethod]属性でマークされたメソッドが呼び出されます。
[InjectionMethod]
public void DoWork([Dependency]IProgramService service)
{
service.DoWork();
}


* This source code was highlighted with Source Code Highlighter .


BuilderAwareStrategy (初期化後)。 OBには、 OnBuiltUpOnTearingDown 2つのメソッドがある特別なIBuilderAwareインターフェイスがあります。 それらをクラスに実装し、オブジェクトを構築(または破棄)するときに、戦略がそれらを呼び出します。 オブジェクトを作成した直後(すべての依存関係が設定されている場合)に何かを開始する必要がある場合に非常に便利です。
#region IBuilderAware Members

public void OnBuiltUp( string id)
{
Console .WriteLine( "Built Up!" );
}

public void OnTearingDown()
{
Console .WriteLine( "Tearing down!" );
}

#endregion


* This source code was highlighted with Source Code Highlighter .


すべての「ネイティブ」OB戦略をリストしました。 エンジンでは、開発者が戦略を追加して、フレームワークの特殊な側面をリンクできるようにします。 残念ながら、OBのすべての側面を完全に分解します。たとえば、名前付きインスタンスは影響を受けません。ポリシーのトピックは完全には開発されていません。 読者は、彼が望めば、自分でそれを理解するだろうと思う:)

実際のアプリケーション、賛否両論でそれを使用する方法


答えは簡単です-インフラストラクチャの側面として。 依存性注入を意味するアーキテクチャをアプリケーションに実装する場合、OBは医師が注文したものです。 OB自体はもともと直接使用するためのものではありませんでした。 CABエンジンでは、そのメソッドは特別なコレクション-OBファサードに変わり、プログラマーの作業を大幅に促進します。

短所:決定の最大、おそらく最大のマイナスは、OBが重いことです。 それはコードを属性でBuildUpせます(属性なしではできません!)そして、そのBuildUpメソッドは、あなたが知っているように、最速のものではありません。 この問題は、クラスグラフ内のリンクを最適化することで解決できます。実際、コードを最大限に分離して依存関係の数を最小限に抑えることができます。
長所:コード、オブジェクト、およびこれに続くすべての接続性が低い。 これは、単体テストのシンプルさ、およびスタンドアロン(ハンドルを設定する必要がない場合)マイクロサービスアーキテクチャなどです。

オブジェクトビルダーの将来と結論。


現在、OBは古くなっています:(はい、申し訳ありませんが、時代遅れの技術に関する記事を書きましたが、基本から始めるのは有益なようです。さらに、Microsoft Object Builder自体が何であるかを理解せずにMicrosoft Object Builder 2について話すことは困難ですマイクロソフトは、CABエンジンを最新のUnityに置き換えます。UnityApplication Blockは、待望のWPFサポートを備えた、より柔軟性の高いプラットフォームです。実際、以下の記事では、CABとは何かを説明し、徐々にUnityに切り替えます。 、ここにリンクがあります:
CAB: msdn.microsoft.com/en-us/library/aa480450.aspx
CAB: www.codeplex.com/smartclient
ユニティ: msdn.microsoft.com/en-us/library/cc468366.aspx
Unity: www.codeplex.com/unity
CABとUnityの違い: www.codeplex.com/CompositeWPF/Release/ProjectReleases.aspx?ReleaseId=16941

ご清聴ありがとうございました。

Source: https://habr.com/ru/post/J48450/


All Articles