MatthiasGは、MEFでモジュールを定義する方法を示しています。ビュー自体はIModuleを実装していないことに注意してください。しかし、PRISMでMEFを使用することの興味深い部分は、起動時にモジュールをUIにインポートする方法です。
ここでは、原則としてシステムを説明することができますが、正しい方向に向けるかもしれません。そこすべてに多くのアプローチは常にありますが、これは私がベストプラクティスとどのような私は非常に良い経験をしたと理解するものである:
プリズムとUnityと同様に
ブートストラップ
、それがすべてで始まりますブートストラップはMefBootstrapper
に由来し、Microsoft.Practices.Prism.MefExtensions
に由来します。ブートストラップはMEFコンテナを設定し、サービス、ビュー、ViewModel、モデルなどのすべてのタイプをインポートします。
エクスポートビュー(モジュール)
これはMatthiasGが参照している部分です。モデルは[Export(typeof(MyModel)]
属性を使用して、(MatthiasGを参照してください、あまりにもインターフェースすることができます)その具体的なタイプとしての地位をエクスポート
:私の練習は、GUIモジュールに次のような構造です。 [PartCreationPolicy(CreationPolicy.Shared)]
とマークすると、インスタンスが1つしか作成されないことを示します(シングルトン動作)。
ビューモデルは単にモデルのように、その具体的なタイプとして自身をエクスポートし、コンストラクタ注射モデルをインポート:
[ImportingConstructor] パブリッククラスMyViewModel(mymodelというモデル) { _model =モデル。 }
Viewはコンストラクタ・インジェクション経由のViewModelをインポートし、同じ方法でのViewModelはモデル
をインポートそして今、これは重要です:由来し、特定の属性を持つビューの輸出そのものを'standard' [Export]
属性。次に例を示します。
[ViewExport(RegionName = RegionNames.DataStorageRegion)]
public partial class DataStorageView
{
[ImportingConstructor]
public DataStorageView(DataStorageViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}
[ViewExport]属性
[ViewExport]
属性には2つのことを行います。それは[Export]
属性から派生しているので、それはビューをインポートするMEFコンテナに指示します。何ですか?これは、それのdefintionに隠されている:コンストラクタのシグネチャは次のようになります。
public ViewExportAttribute() : base(typeof(UserControl)) {}
UserControl
の種類と[Export]
のコンストラクタを呼び出すことで、すべてのビューは、MEFコンテナ内UserControl
として登録されます。
第2に、ビューをプラグインするシェルUIの領域を決定するために後で使用されるプロパティRegionName
を定義します。 RegionNameプロパティは、インターフェイスIViewRegionRegistration
の唯一のメンバです。属性クラス:AutoPopulateExportedViews
行動:ビュー
をインポート
/// <summary>
/// Marks a UserControl for exporting it to a region with a specified name
/// </summary>
[Export(typeof(IViewRegionRegistration))]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
[MetadataAttribute]
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration
{
public ViewExportAttribute() : base(typeof(UserControl)) {}
/// <summary>
/// Name of the region to export the View to
/// </summary>
public string RegionName { get; set; }
}
は今、システムの最後の重要な部分はあなたのシェルの部分に取り付け行動、です。これは、この行とMEFコンテナから、あなたのモジュールのすべてをインポート:彼らはIViewRegionRegistration
を実装するメタデータ属性を、持っている場合
[ImportMany]
private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews;
これは、コンテナからUserControl
として登録されているすべての種類をインポートします。 [ViewExport]
属性が実行するため、[ViewExport(...)]
とマークされたすべてのタイプをインポートすることを意味します。
/// <summary>
/// A behavior to add Views to specified regions, if the View has been exported (MEF) and provides metadata
/// of the type IViewRegionRegistration.
/// </summary>
[Export(typeof(AutoPopulateExportedViewsBehavior))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class AutoPopulateExportedViewsBehavior : RegionBehavior, IPartImportsSatisfiedNotification
{
protected override void OnAttach()
{
AddRegisteredViews();
}
public void OnImportsSatisfied()
{
AddRegisteredViews();
}
/// <summary>
/// Add View to region if requirements are met
/// </summary>
private void AddRegisteredViews()
{
if (Region == null) return;
foreach (var view in _registeredViews
.Where(v => v.Metadata.RegionName == Region.Name)
.Select(v => v.Value)
.Where(v => !Region.Views.Contains(v)))
Region.Add(view);
}
[ImportMany()]
private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews;
}
お知らせ.Where(v => v.Metadata.RegionName == Region.Name)
:
最後のステップは、それがOnAttach()
プロパティの中bahviorがない領域にビューをプラグインすることです。これは、属性のRegionNameプロパティを使用して、特定のリージョンに対してエクスポートされたビューのみを取得し、ビヘイビアをアタッチしています。
動作がブートストラップであなたのシェルの地域に添付されます:私たちは完全な円を来ている
protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
ViewModelInjectionBehavior.RegionsToAttachTo.Add(RegionNames.ElementViewRegion);
var behaviorFactory = base.ConfigureDefaultRegionBehaviors();
behaviorFactory.AddIfMissing("AutoPopulateExportedViewsBehavior", typeof(AutoPopulateExportedViewsBehavior));
}
、私は願って、これはあなたに物事がMEFと場所に分類方法のアイデアを取得し、プリズム。
そして、あなたはまだ退屈いないのであれば:これは完璧です:
Mike Taulty's screencast
は、ビューのコンストラクタでのビュー・モデルは良い方法です初期化します。あなたはどんな問題をそれのようにしていますか? – thumbmunkeys
Unityでは、コンテナを介してビューモデルを初期化します。それは私にmefで同等の方法を検索させますか?しかし、もしあなたがそれを良い方法と言えば、私は多くのことを固くはしません。 – user2147528