0

プレゼンテーション ロジック層 (PLL) には、ビジネス ロジック層 (BLL) で定義された /extend インターフェイスを実装するいわゆる「ビュー モデル」クラスがあります。

namespace BLL.Abstract.POCO
{
    // also implemented in data access layer (DAL) by data model entities
    public interface ISomeDomainModelEntity
    {
        string Name { get; set; }
        string Description { get; set; }
    }
}

namespace PLL.Abstract.ViewModels
{
    public interface ISomeDomainModelEntityViewModel 
                     : ISomeDomainModelEntity, INotifyPropertyChanged
    {
        bool IsSelected { get; set; }
    }     
}

namespace PLL.Concrete.ViewModels
{
    public class SomeDomainModelEntityViewModel 
                 : ViewModelBase, ISomeDomainModelEntityViewModel
    {
        private string _name;
        private string _description;
        private bool _isSelected;

        public string Name { get { return _name; } set { _name = value; NotifyPropertyChanged(() => Name); } }
        public string Description { get { return _description; } set { _description = value; NotifyPropertyChanged(() => Description); } }
        public bool IsSelected { get { return _isSelected; } set { _isSelected = value; NotifyPropertyChanged(() => IsSelected); } }
    }
}

は、この手の込んだ厳密に型指定された実装ViewModelBaseを可能にする抽象クラスであることに注意してください。INotifyPropertyChanged

上記の実装のIsSelectedプロパティは、明らかにプレゼンテーション レイヤーでのみ必要であり (プロパティを にバインドするItemTemplate機能を持つリストに表示される数十個のこれらのオブジェクトを視覚化します)、プレゼンテーション ロジックは、ビジネスに戻る前にそれを使用する方法を知っています。ロジック層。ListBoxIsCheckedIsSelected

私が抱えている問題は、「ViewModel」という名前がこれと衝突していることです。

namespace PLL.Abstract.ViewModels // hmmm...
{
    public interface ISomeWindowViewModel
    {
        ObservableCollection<ISomeDomainModelEntityViewModel> SomeItems { get; }
    }
}

の実装は、ISomeWindowViewModel最終的にビューのDataContextプロパティに割り当てられます。

namespace PLL.Concrete.ViewModels
{
    public class SomeWindowViewModel : WindowViewModelBase, ISomeWindowViewModel
    {
        private readonly ObservableCollection<ISomeDomainModelEntityViewModel> _items;

        public SomeWindowViewModel(IView view, ObservableCollection<ISomeDomainModelEntityViewModel> items)
            : base(view)
        {
            _items = items;
        }

        public ObservableCollection<ISomeDomainModelEntityViewModel> SomeItems { get { return _items; } set { _items = value; } }
    }
}

namespace PLL.Abstract
{
    public abstract class WindowViewModelBase : ViewModelBase
    {
        public IView View { get; private set; }

        protected WindowViewModelBase(IView view)
        {
            View = view;
            View.DataContext = this;
        }
    }
}

これは、Mark Seeman の.NET での Dependency Injection でDI を WPF に適用する方法について読んだ後に開始した主要なリファクタリングの結果です(これまでのところ非常によく読んでいますが、まだ終わっていません)。ビューの実装をビューモデルに挿入すると、ビューの表示とクローズを処理することで得られた制御/簡素化を理解できます。リファクタリングの前に、DAL および PLL と密接に結合された BLL を使用するアプリケーションが動作していました。現在、BLL には依存関係がまったくありません。これはすばらしいことです。

私はまだコンポジション ルートを (Ninject.Extension.Conventions を使用して) 再構成している最中なので、1 日の終わりには、すべてを機能させるためにいくつかの調整を行う必要があることに気付くかもしれません...痛いかもしれませんが、準備はできています!

したがって、質問は次のとおりです。

  • インターフェイスが多すぎるように感じますが、慣例を使用した DI 構成では完全にグリーンです (まあ、DI では完全にグリーンです!)。型がインターフェイスを実装する場合、慣例に従ってICコンテナーを構成するのははるかに簡単に思えます...しかし、これはやり過ぎですか?
  • ここで「ViewModel」という用語が乱用されていますか? むしろ、「ViewModel」と「WindowViewModel」の区別は保証されていますか、それとも何か不足していますか? ViewModel が他の ViewModel を「含む」のは正常ですか? そうでない場合、View で DataContext として使用される ViewModel に「WindowViewModel」という名前を付けてもよろしいですか?
  • コードベースをめちゃくちゃにしてしまう明らかなアーキテクチャ上の欠陥はありますか? アイデアは、DI を使用して MVVM を可能な限りしっかりと実装することですが、まだ学ぶべきことがたくさんあると思います。
  • この投稿をタイプしているときに、昨年のこの質問が「類似の質問」リストに表示され、私の頭の中で物事がさらにぼやけ始めています - 受け入れられた回答と他のコメントは、私が最近読んだものと根本的に矛盾しています. 具体的には、ViewModel クラスに IView 実装を注入する必要があります。この質問/回答 + コメントは正反対のことを言っています。どちらの方法も完全に受け入れられるように見えますが、それは個人的な好みの問題ですか?
4

1 に答える 1

1
  1. 私の意見では、多すぎます。アーキテクチャは柔軟であるべきであり、IOC のような技術に固執し続けることはできないかもしれません。ISomeDomainModelEntityViewModel、ISomeWindowViewModel、および IObservableCollection の利点がわかりませんでした。DI を除いて、各インターフェイスには 1 つのクラスしかありません。また、インターフェイスは DI に必須ではありません。Prism の例を見て、DI を使用して ViewModel を構築する方法と、いつインターフェイスを使用するかを確認してください。通常、DI を使用して ViewModel を構築する場合、ViewModel のすべての依存関係はサービスであり、インターフェイスで定義され、IOC を使用してこれらのサービスを解決します。これらのサービスには外部依存関係があるため、これらのインターフェイスをモックしてテストするのは簡単です。でも、

  2. メインの ViewModel には各ページの子が含まれているなど、ViewModel に他の ViewModel を含めることができると思います。

  3. 明確ではない。インターフェイス以外に、個人的には IObservableCollection を IOC に入れるのは良い方法ではないと思います。

  4. 個人的には、ViewModel は View を認識できないため、IView を注入すると MVVM が壊れると思います。IView、ViewModel でさえ、View への参照を持っています。ただし、一部のシナリオでは、その ViewModel に IView があれば、多くのことがはるかに簡単になります。私が言ったように、アーキテクチャは柔軟であるべきです。

それが役立つことを願っています。

于 2013-07-11T21:57:48.510 に答える