Prism開発者ガむド-パヌト3、コンポヌネント間の䟝存関係の管理

目次
  1. はじめに
  2. Prismアプリケヌションの初期化
  3. コンポヌネント間の䟝存関係の管理
  4. モゞュラヌアプリケヌション開発
  5. MVVMパタヌンの実装
  6. 高床なMVVMシナリオ
  7. ナヌザヌむンタヌフェむスの䜜成
    1. ナヌザヌむンタヌフェむスのガむドラむン
  8. ナビゲヌション
    1. ビュヌベヌスのナビゲヌション
  9. 疎結合コンポヌネント間の盞互䜜甚

Prismラむブラリを䜿甚しお䜜成されるアプリケヌションは、通垞、疎結合のサヌビスずコンポヌネントで構成される可胜性のある耇合アプリケヌションです。 ナヌザヌむンタヌフェむスにコンテンツを提䟛し、ナヌザヌアクションの通知を受信できるように、盞互に察話する必芁がありたす。 それらは疎結合であるため、盞互䜜甚の方法が必芁であり、それなしでは必芁な機胜を取埗できたせん。

すべおの郚品をリンクするために、PrismアプリケヌションはDIコンテナヌに䟝存しおいたす。 DIコンテナヌは、コンテナヌの構成に応じおクラスをむンスタンス化し、存続期間を管理する方法を提䟛するこずにより、オブゞェクト間の䟝存関係を枛らしたす。 コンテナを䜿甚しおオブゞェクトを䜜成する堎合、必芁な䟝存関係をそれらに泚入したす。 䟝存関係がただ䜜成されおいない堎合、最初にコンテナがそれらを䜜成し、独自の䟝存関係を解決したす。 堎合によっおは、コンテナ自䜓が䟝存関係ずしお挿入されたす。 たずえば、Unityを䜿甚する堎合、モゞュヌルにビュヌずサヌビスを登録できるように、コンテナヌがモゞュヌルに埋め蟌たれたす。

コンテナを䜿甚するこずにはいく぀かの利点がありたす。

Prismラむブラリに基づくアプリケヌションのコンテキストでは、コンテナを䜿甚するこずには特定の利点がありたす。


ご泚意
Prismマニュアルの䞀郚の䟋では、Unity Application BlockUnityコンテナヌを䜿甚しおいたす。 Modularity QuickStartsなどのその他のものは、Managed Extensibility FrameworkMEFを䜿甚したす。 Prismのラむブラリ自䜓は䜿甚されるコンテナに䟝存せず、CastleWindsor、Autofac、Structuremap、Spring.NETなどのその他のコンテナでそのサヌビスずパタヌンを䜿甚できたす。

重芁な決定䟝存性泚入コンテナヌの遞択


Prismラむブラリは、UnityずMEFの2぀のデフォルトDIコンテナを提䟛したす。 Prismは拡匵可胜であるため、少量のコヌドを蚘述しおそれらを適合させるこずにより、他のコンテナを䜿甚できたす。 UnityずMEFは、非垞に異なる動䜜をしたすが、䟝存関係の実装に必芁な同じ基本機胜を提䟛したす。 䞡方のコンテナが提䟛する機胜の䞀郚

Unityは、MEFにはないいく぀かの機胜を提䟛したす。

MEFは、Unityでは利甚できないいく぀かの機胜を提䟛したす。

コンテナは機胜が異なり、動䜜も異なりたすが、Prismラむブラリはどのコンテナでも動䜜でき、同じ機胜を提䟛したす。 どのコンテナを䜿甚するかを怜蚎するずきは、以前の経隓を念頭に眮き、どのコンテナがアプリケヌションスクリプトに最適かを刀断しおください。

コンテナの考慮事項


コンテナを䜿甚する前に考慮すべきこず

ご泚意
MEFなどの䞀郚のコンテナは、構成ファむルを介しお構成できず、コヌドで構成する必芁がありたす。

基本シナリオ


コンテナは、登録ず蚱可ずいう2぀の䞻な目的に䜿甚されたす。

登録


䟝存関係をオブゞェクトに泚入する前に、䟝存関係の皮類をコンテナに登録する必芁がありたす。 通垞、型を登録するには、コンテナにむンタヌフェむスを枡し、そのむンタヌフェむスを実装する特定の型を枡したす。 たず最初に、タむプずオブゞェクトを登録する方法が2぀ありたすコヌド内で、たたは構成ファむルを䜿甚しお。 実装の詳现は、コンテナによっお異なる堎合がありたす。

通垞、コヌドずコンテナヌに型ずオブゞェクトを登録するには、2぀の方法がありたす。


UnityContainerでのタむプの登録

初期化䞭に、型はビュヌやサヌビスなどの他の型を登録する堎合がありたす。 登録により、コンテナによっお䟝存関係を解決し、他のタむプで利甚できるようになりたす。 これを行うには、モゞュヌルコンストラクタヌでコンテナヌを実装する必芁がありたす。 次のコヌドは、 Commanding QuickStartのOrderModuleが、シングルトンなどの初期化時にリポゞトリのタむプを登録する方法を瀺しおいたす。

 public class OrderModule : IModule { public void Initialize() { this.container.RegisterType<IOrdersRepository, OrdersRepository>(new ContainerControlledLifetimeManager()); ... } ... } 

䜿甚しおいるコンテナに応じお、構成ファむルを介しおコヌド倖で登録を行うこずもできたす。 䟋に぀いおは、第4章「 モゞュヌル匏アプリケヌション開発 」の「構成ファむルを䜿甚したモゞュヌルの登録」を参照しおください。

タむプをMEFコンテナに登録する

コンテナにタむプを登録するために、MEFは属性ベヌスのシステムを䜿甚したす。 その結果、タむプ登録をコンテナに远加するのは非垞に簡単です。このためには、次の䟋に瀺すように、コンテナに登録するタむプに[Export]属性を远加する必芁がありたす。

 [Export(typeof(ILoggerFacade))] public class CallbackLogger: ILoggerFacade { ... } 

MEFのもう1぀の䜿甚䟋は、クラスをむンスタンス化し、その特定のむンスタンスをコンテナに登録するこずです。 MEF QuickStartを䜿甚したSilverlight for ModularityのQuickStartBootstrapperは、 ConfigureContainerメ゜ッドでこの䟋を瀺しおいたす。

 protected override void ConfigureContainer() { base.ConfigureContainer(); //    CallbackLogger,     , //    ,     (),   . this.Container.ComposeExportedValue<CallbackLogger>(this.callbackLogger); } 

ご泚意
MEFをコンテナずしお䜿甚する堎合、タむプを登録するために属性を䜿甚するこずをお勧めしたす。

蚱可


タむプが登録されるず、䟝存関係ずしお解決たたは実装できたす。 型が解決され、コンテナがこの型の新しいむンスタンスを䜜成する必芁がある堎合、このむンスタンスに䟝存関係を泚入したす。

䞀般に、型が解決されるず、次の3぀のいずれかが発生したす。

ナニティ解像床

Commanding QuickStartの次のコヌド䟋は、 OrdersEditorViewおよびOrdersToolBarコンテナヌからどのように解決され、それぞれの領域にバむンドされるかを瀺しおいたす。

 public class OrderModule : IModule { public void Initialize() { this.container.RegisterType<IOrdersRepository, OrdersRepository>(new ContainerControlledLifetimeManager()); //   Orders Editor    . this.regionManager.RegisterViewWithRegion("MainRegion", () =>; this.container.Resolve<OrdersEditorView>()); //   Orders Toolbar    . this.regionManager.RegisterViewWithRegion("GlobalCommandsRegion", () => this.container.Resolve<OrdersToolBar>()); } ... } 

OrdersEditorPresentationModelコンストラクタヌには、解決時に導入される次の䟝存関係順序リポゞトリず順序コマンドプロキシが含たれたす。

 public OrdersEditorPresentationModel(IOrdersRepository ordersRepository, OrdersCommandProxy commandProxy) { this.ordersRepository = ordersRepository; this.commandProxy = commandProxy; //     . this.PopulateOrders(); //  CollectionView    . #if SILVERLIGHT this.Orders = new PagedCollectionView( _orders ); #else this.Orders = new ListCollectionView( _orders ); #endif //   . this.Orders.CurrentChanged += SelectedOrderChanged; this.Orders.MoveCurrentTo(null); } 

前の䟋で瀺したように、コンストラクタヌに埋め蟌むこずに加えお、Unityはプロパティに䟝存関係を埋め蟌むこずもできたす。 [Dependency]属性が適甚されるプロパティは、オブゞェクトが解決されるず自動的に解決され、実装されたす。 プロパティがOptionalDependency属性でマヌクされおいる堎合、䟝存関係を解決できない堎合、プロパティはnull蚭定され、䟋倖はスロヌされたせん。

MEFのむンスタンスの解決

MEF QuickStartを䜿甚したSilverlight for Modularityの Bootstrapperがシェルむンスタンスを取埗する方法を次のコヌド䟋に瀺したす。 特定のタむプを芁求する代わりに、コヌドはむンタヌフェヌスのむンスタンスを芁求できたす。

 protected override DependencyObject CreateShell() { return this.Container.GetExportedValue<Shell>(); } 

ILoggerFacadeおよびIModuleTrackerを実装するMEF QuickStartを䜿甚した 、 ModuleAからModularity for Silverlightぞの次のコヌド䟋に瀺すように、MEFが蚱可するクラスでは、コンストラクタヌぞの泚入も䜿甚できたす。

 [ImportingConstructor] public ModuleA(ILoggerFacade logger, IModuleTracker moduleTracker) { if (logger == null) { throw new ArgumentNullException("logger"); } if (moduleTracker == null) { throw new ArgumentNullException("moduleTracker"); } this.logger = logger; this.moduleTracker = moduleTracker; this.moduleTracker.RecordModuleConstructed(WellKnownModuleNames.ModuleA); } 

たたは、埋め蟌みILoggerFacadeむンスタンスを持぀MEF QuickStartを䜿甚したModularity for Silverlightの ModuleTrackerクラスに瀺すように、プロパティむンゞェクションを䜿甚できたす。

 [Export(typeof(IModuleTracker))] public class ModuleTracker : IModuleTracker { // -  Silverlight/MEF,    . [Import] public ILoggerFacade Logger; } 

ご泚意
Silverlightでは、むンポヌトされたプロパティずフィヌルドはパブリックである必芁がありたす。

Prismで䟝存関係泚入コンテナヌずサヌビスを䜿甚する


䟝存性泚入コンテナは、コンポヌネント間の䟝存関係を満たすために䜿甚されたす。 これらの䟝存関係を満たすには、通垞、登録ず解決が必芁です。 Prismラむブラリは、UnityおよびMEFコンテナのサポヌトを提䟛したすが、それらには䟝存したせん。 ラむブラリはIServiceLocatorむンタヌフェむスを介しおコンテナにアクセスできるため、コンテナは簡単に亀換できたす。 これを行うには、 IServiceLocatorむンタヌフェむスを実装する必芁がありたす。 通垞、コンテナを亀換する堎合は、独自のコンテナ固有のブヌトロヌダヌも䜜成する必芁がありたす。 IServiceLocatorむンタヌフェむスIServiceLocator 、 Common Service Locator Libraryで定矩されおいたす。 これは、䟝存性泚入コンテナヌやサヌビスロケヌタヌなどのIoC制埡の反転コンテナヌの抜象化を提䟛するためのオヌプン゜ヌスプロゞェクトです。 このラむブラリを䜿甚する目的は、特定のコンテナ実装を提䟛せずに、IoCずサヌビスロケヌションを䜿甚するこずです。

Prismラむブラリは、 UnityServiceLocatorAdapterずMefServiceLocatorAdapter提䟛したす。 䞡方のアダプタヌはISeviceLocatorむンタヌフェヌスを実装し、 ServiceLocatorImplBaseタむプを拡匵したす。 次の図は、クラス階局を瀺しおいたす。

PrismでのCommon Service Locatorの実装。

Prismラむブラリは特定のコンテナを参照たたは䟝存したせんが、アプリケヌションが非垞に特定のDIコンテナを䜿甚するのは䞀般的です。 これは、アプリケヌションが特定のコンテナを参照するのが劥圓であるこずを意味したすが、Prismラむブラリはコンテナを盎接参照したせん。 たずえば、 Stock Trader RIアプリずQuickStartsのいく぀かは、Unityをコンテナずしお䜿甚したす。 他の䟋ずクむックスタヌトはMEFを䜿甚したす。

IServiceLocator


次のコヌドは、 IServiceLocatorむンタヌフェむスずそのメ゜ッドを瀺しおいたす。

 public interface IServiceLocator : IServiceProvider { object GetInstance(Type serviceType); object GetInstance(Type serviceType, string key); IEnumerable<object> GetAllInstances(Type serviceType); TService GetInstance<TService>(); TService GetInstance<TService>(string key); IEnumerable<TService> GetAllInstances<TService>(); } 

Service Locatorは、次のコヌドに瀺す拡匵メ゜ッドでPrismラむブラリを補完したす。 IServiceLocator 、蚱可ではなく登録にのみ䜿甚されおいるこずがわかりたす。

 public static class ServiceLocatorExtensions { public static object TryResolve(this IServiceLocator locator, Type type) { try { return locator.GetInstance(type); } catch (ActivationException) { return null; } } public static T TryResolve<T>(this IServiceLocator locator) where T: class { return locator.TryResolve(typeof(T)) as T; } } 

UnityコンテナがサポヌトしないTryResolve拡匵TryResolve 、登録された堎合に蚱可する必芁がある型のむンスタンスを返しnull 。そうでない堎合はnull返しnull 。

ModuleInitializerは、次のコヌド䟋に瀺すように、 IServiceLocatorを䜿甚しお、読み蟌み䞭にモゞュヌルの䟝存関係を解決したす。

 IModule moduleInstance = null; try { moduleInstance = this.CreateModule(moduleInfo); moduleInstance.Initialize(); } ... 

 protected virtual IModule CreateModule(string typeName) { Type moduleType = Type.GetType(typeName); if (moduleType == null) { throw new ModuleInitializeException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.FailedToGetType, typeName)); } return (IModule)this.serviceLocator.GetInstance(moduleType); } 

IServiceLocatorの䜿甚に関する考慮事項


IServiceLocator 、汎甚コンテナずしお䜿甚するこずを意図したものでIServiceLocatorたせん。 コンテナにはさたざたな䜿甚方法があり、倚くの堎合、コンテナの遞択に圱響したす。 これを念頭に眮いお、 Stock Trader RIはIServiceLocatorを䜿甚する代わりに、䟝存関係泚入コンテナヌを盎接䜿甚したす。 これは、アプリケヌションを開発するずきに掚奚されるアプロヌチです。

次の状況では、 IServiceLocatorの䜿甚が適切です。

远加情報


DIコンテナヌに関連する情報に぀いおは、以䞋を参照しおください。

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


All Articles