レイヤー+ Unityコンテナー

みなさんこんにちは! レイヤーアーキテクチャの例と、その中のUnityコンテナーの役割を示します。 そして、人々はコンテナ自体について書きますが、それを正しく使用する方法を実際に書くことはできません。 試してみましょう。





すぐに開始しますが、すぐに申し訳ありません。 単純に、有用な何かを説明するためには、本当に有用な何かを考え出す必要があります。



(それほどではない)人生の例



あなたがクールな開発者であり、2人の友人プログラマーであるKolyanとTolyanがあるとします。 KolyanとTolyanは誰にとっても優れていますが、経験はほとんどなく、その結果コードの品質が低下しますが、あなたはそれらと友達であり、時には一緒にプロジェクトを行うことさえあります。



今-突然、どこからともなく、IBBCの顧客があなたに電話して叫ぶ:

-ボロディア! 画面にオブジェクトを表示するアプリケーションを早急に取得する必要があります! 締め切り週。 お金-百万!

そして電話を切ります。



設計は設計から始まるため、設計します。



レイヤーとブラックボックス



システムをレイヤー上に構築します。



Microsoft Architecture Application Guideのソフトウェア層の定義は次のとおりです(多少自由に翻訳できますが、申し訳ありません)。



レイヤーは、アプリケーションまたはサービスを構成するソフトウェアコンポーネントの論理的なグループです。



つまり、「階層化アーキテクチャ」では、アプリケーションを構成するソフトウェアコンポーネントの非常に多くの部分が、論理的に関連するいくつかのサブセットに分割されます。 UI層、ビジネスロジック層、データ層など、このジャンルの古典を誰もが知っています。



顧客から判断すると、ユーザーインターフェイスに何かを表示し、何らかのソースからデータを収集する必要があります。 したがって、システムは、UIレイヤー、データレイヤー、およびドライバー(レイヤーとメイン()を接続する)の2つのレイヤーで構成されます。



KolyanがUIを作成し、Tolyanがデータレイヤーを作成することに同意しました。 調整活動を実行し、ドライバープログラムと横断的なコードを記述します。



ブラックボックス



レイヤーは、ソフトウェアモジュール(1つ以上の.netのメインのアセンブリ)です。 このモジュールは、ブラックボックスまたはホワイトボックスとして実装できます。



つまり、ブラックボックスの内容はわかりませんが、コントロールパネル(インターフェイス)があります。

白いボックスでは、あなたがボスです-あなたが望むものは何でも、あなたはそのコンテンツでそれをします。 それは透明であり、すべての内部が見えます。



私たちの場合、ブラックボックス法を使用してレイヤーを設計することはコーシャーです。それが理由です:

  1. 概念的な整合性とカプセル化を実現します。 インターフェイスを介してレイヤーにアクセスするための単一のメカニズムを開発すると、ボックスエンティティでのみ操作できるセマンティックな完全性(つまり、有限性)が得られます。
  2. カプセル化と(最も重要なことですが)レイヤーの特定のエンティティの構築方法に関する無知により、より一般的な問題に集中することができ、不必要な微妙さを気にする必要がなくなります。
  3. 最後に、これらの仮定は最高のプログラミングマインドによって私たちに伝えられているので、スマートな叔父に耳を傾けましょう:)




コンテナとその役割



上記のすべてから、次のような方法でソフトウェアモジュールを整理する必要があることがわかります。

  1. 彼に割り当てられた契約を実施した
  2. 特定のエンティティの実装全体を隠す


すべての実装をボックスにカプセル化するため、それらに直接アクセスして通常の方法で作業することはできません。 何らかの形でボックスコントラクトとその実装を関連付け、どこかに保存して、プロセスの他の参加者が使用できるようにする必要があります。 このためには、コンテナが必要です。 最も退化したケースでは、通常の辞書「インターフェイス固有のタイプ」です。 たとえばUnityのように、より複雑なケースでは、依存関係インジェクターやブラックジャックを持つその他の売春婦でもあります。



アプリケーションの起動時に、コンテナをレイヤーに浸し、レイヤーがバインドしているコントラクトの実装を登録できるようにする必要があります。 すべての実装が組み立てられた後、私たちが誰であるかを心配することなく、すでに制御コードを書くことができます。



あなたはこれをすべて頭の中で計画しました(なんて素晴らしい仲間です)。今、開発段階に進みます。



コード





契約アセンブリが必要です。 あなたはそれらのいくつかを作ることができます-各レイヤーに対して。 しかし、簡単にするために、一般的なことを1つ行います。

Tolyanは私たちとデータにアクセスします。 その層にこれを実装させます:



public interface IDataService

{

object GetData();

}




* This source code was highlighted with Source Code Highlighter .








それに応じて、KolyanはUIを取得しました。



public interface IDataView

{

void ShowData();

}



public interface IViewFactory

{

IDataView Create(Type viewType);

}




* This source code was highlighted with Source Code Highlighter .








プログラムモジュールには唯一のパブリッククラスが含まれている必要があります。そのため、コンテナを入れていくつかの実装をすくうことができます。



public interface IModule

{

void Configure(IUnityContainer container);

}




* This source code was highlighted with Source Code Highlighter .








すべての契約が定義されています。 ここで、すべてを制御アプリケーションにまとめる必要があります。

class ShellApplication

{

public ShellApplication()

{

_container = new UnityContainer();

}



public void Run()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault( false );



_container.RegisterInstance<IUnityContainer>(_container);

_container.Resolve<Layers.Data.Module>().Configure(_container);

_container.Resolve<Layers.UI.Module>().Configure(_container);



MainForm form = (MainForm)_container.Resolve( typeof (MainForm));



Application.Run(form);

}



private IUnityContainer _container;

}




* This source code was highlighted with Source Code Highlighter .








partial class MainForm : Form

{

public MainForm(IViewFactory factory)

{

InitializeComponent();

_factory = factory;

}



protected override void OnLoad( EventArgs e)

{

base .OnLoad(e);



IDataView view = _factory.Create( typeof (IDataView));

Controls.Add((Control)view);

view.ShowData();

}



private IViewFactory _factory;

}




* This source code was highlighted with Source Code Highlighter .








すべてはあなたの側にあります。



ここで、KolyanとTolyanに目的のコードを作成させる必要があります。 適切な器用さで、すべての部分を並行して同時に書くことができます。 したがって、デザインの美しさは、そのシックなスケーラビリティです。 すべてが適切に計画されていれば、モジュール層の開発は他の部分に気を取られることなく、活発かつ迅速に開始されます。



反復もサポートされています-降順で記述できます。 最初に、制御コードを記述し、「偽のレイヤー」をその上に置いて、反復で契約を要件に変更する必要があります。 制御コードがデバッグおよび修正された後、コーナーをスイープするために残ります-ボックスを実装します。



Kolyan、Tolyanと私はこれを得ました:



見て、周りに封筒だけがあります。 レイヤーは、モジュールのクラスであるテールのみを突き出しました。



そして、私たちはIBBCから農民に彼の申請を行い、多くのお金を集めました。 トリヤンとコリャンは数十個を買いました、そして私-事前。



待って 私はほとんど忘れていました。 「ハハハハ!!! 吸盤! 吸盤!」、ヘンリー・ロリンズが彼の非常に良い歌の 4分の終わりにしたのとほぼ同じ。 どのようにすべての実装を非表示にしましたが、単体テストを非表示にしましたか?!?!



さて、私はこれを行います:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo( "Services.Tests, PublicKey=00240000048000009[skipped]1fbcb51f56dfcc8db5320774f354553ad" )]



* This source code was highlighted with Source Code Highlighter .








説明する必要はありませんか?:)



機能、結論、メモ、ボーナス、デメリット





申し訳ありませんが、Windows Formsでサンプルを作成しています。 ASP.NET MVCアプリケーションのアーキテクチャをこのような方法で配置する方法をお伝えしたいのですが、私の友人であるXaocCPSがこれに勝てます。 私は戦うのが大好きですが、彼はより速くて大きいです。 このトピックは彼にお任せください。



1)コントロールアセンブリには、すべてのレイヤーおよびコントラクトのアセンブリへのリンクが必要です。 そうしないと、実装を収集できません。



2)KolyanはTolyanデータサービスを使用する必要がありました(パラダイムによれば、UIレイヤーはデータレイヤーに依存します)。



partial class DataView : UserControl, IDataView

{

public DataView(IDataService data)

{

InitializeComponent();

_dataService = data;

listBox1.DataSource = _source;

}



#region IDataView Members



public void ShowData()

{

_source.DataSource = _dataService.GetData();

}



#endregion



private IDataService _dataService;

private BindingSource _source = new BindingSource();

}




* This source code was highlighted with Source Code Highlighter .








しかし、UIレイヤーよりも前にデータレイヤーの依存関係を解決し、Unityコンテナーの異常なストリートマジックを解決するという事実により、依存関係の設定に問題はありません。



そのため、Tolyanは自分のレイヤーにIModuleを実装しました。

public class Module : IModule

{

#region IModule Members



public void Configure(Microsoft.Practices.Unity.IUnityContainer container)

{

container.RegisterType( typeof (IDataService), typeof (DataService));

}



#endregion

}




* This source code was highlighted with Source Code Highlighter .








3)おそらく、説明したアプローチの主な利点はカプセル化です。 インターフェースを使用して動作します。 それらの背後にあるものを知る必要はありません。 TolyanまたはKolyanのわずかな不十分さで、私たちは彼が書いたものをすべて捨て、私たちのものを(合法的に)別のコードの安全性に対して完全に自信を持って書きます。 あなただけの交換ボックス契約を実装する必要があります:D



4)団結に関する記事の中で、誰かが完全に素晴らしい質問をしました。



そのような単純な例のために



var svc = new MyService(10);







よりずっと良く見える



var uc = new UnityContainer();

uc.RegisterType<IService, MyService>();

uc.RegisterType(new InjectionConstructor(10));

var svc = uc.Resolve();








私は彼の誤解を明確にしたと思います。



5)一般的に、Unityコンテナは、MS-Unity Application Blockからの依存性インジェクターおよび新しいフレームワークのオブジェクトのファクトリを対象としています。 そして、彼は私たちにフレームワークの壁の外側でそれを使用しないほうが良いと言っているようですが、そのアプリケーションの可能性は本当に非常に広いです。



6)コードで指定されたフォームとユーザーコントロールは、MVPテンプレートを介してリファクタリングする必要があります。 しかし、これはアマチュアです:)



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






All Articles