2

最初の警告: 長い投稿で、とにかくパターンが完全に間違っている可能性があります:

Customer Aggregate の開始である次のクラスがあるとします。

public class Customer : KeyedObject
{

   public Customer(int customerId)
   {
      _customerRepository.Load(this);
   }

   private ICustomerRepository _customerRepository = IoC.Resolve(..);  
   private ICustomerTypeRepository = _customerTypeRepository = IoC.Resolve(..);

   public virtual string CustomerName {get;set;}
   public virtual int CustomerTypeId [get;set;}

   public virtual string CustomerType
   {
      get
      {
         return _customerTypeRepository.Get(CustomerTypeId);
      }
   }

}

また、CustomerType は値オブジェクトで表されます。

public class CustomerType : ValueObject
{
   public virtual int CustomerTypeId {get;set;}
   public virtual string Description {get;set;}
}

CustomerTypeId を持つ顧客オブジェクトがある場合は、これで十分です。ただし、MVC ビュー内に DropDownList を設定する場合、ICustomerTypeRepostory から CustomerType 値リストを正しく取得する方法の概念に苦労しています。

ICustomerTypeRepository非常に簡単です。

public interface ICustomerTypeRepository
{
   public CustomerType Get(int customerTypeId);
   public IEnumerable<CustomerType> GetList();
}

基本的にはコントローラーから正しく呼び出せるようにしたいのですがICustomerTypeRepository、コントローラーからDAL(リポジトリ)レイヤーを分離するのが一番いいと思いました。さて、私は物事を過度に複雑にしていますか?

これが私のコントローラーの現在の状態です。

public class CustomerController : ControllerBase
{ 

    private ICustomerTypeRepository _customerTypeRepository = IoC.Resolve(..);

    public ActionResult Index()
    {
       Customer customer = new Customer(customerId); 
       IEnumerable<CustomerType> customerTypeList = 
          _customerTypeRepository.GetList();

       CustomerFormModel model = new CustomerFormModel(customer);
       model.AddCustomerTypes(customerTypeList );
    }
}

Controller と Customer にリポジトリがあるので、これは私には間違っているようです。CustomerType 用に分離されたアクセス レイヤーが必要であることは、私には論理的に思えます。すなわちCustomerType.GetList()

public class CustomerType : ValueObject
{
   // ... Previous Code

   private static ICustomerTypeRepository _customerTypeRepository = IoC.Resolve(..);

   public static IEnumerable<CustomerType> GetList()
   {
      _customerTypeRepository.GetList();
   }
}

では、オブジェクトを からに公開する方法どれですか?CustomerTypeICustomerTypeRepositoryCustomerController

4

2 に答える 2

2

ここで考慮すべき点がいくつかあると思います。

まず第一に、ドメインのモデル化に本当に関心がある場合は、ドメイン エンティティ自体を、検証、IoC コンテナー、永続性などの分野横断的な問題から解放するために、どんな犠牲を払っても試してみることをお勧めします。ただし、Active Record パターンは無視します。

これが意味することは、Customerインターフェースとサービスロケーターを使用している場合でも、おそらくリポジトリへの参照を持たないことです。対象となるクライアント/ユーザーの観点から、「顧客」の属性 (または構成要素) を反映するように設計する必要があります。

IoCドメインモデリングは別として、変数初期化子でのサービスロケーターの使用について少し心配しています。例外をキャッチする機会を失い、コンストラクターによってスローされた例外はデバッグが難しいことで有名です (これらの初期化子は、最初の非静的コンストラクターのコードの前に実行されます)。

依存関係を注入する代わりに静的ゲートウェイ/サービス ロケーターを使用すると、クラスが事実上テスト不可能になります (自動化された単体テスト方法論を使用すると、つまり、統合と手動テストを行うことができますが、テストの失敗によって壊れた部分が指摘されることはほとんどありません)。何をテストしているのか、つまり何が壊れているのかを正確に把握している単体テストとは対照的です)。

Customerコンストラクターを呼び出してオブジェクト自体にデータを入力する代わりに_customerRepository.Load(this)、アプリケーションは通常、リポジトリを使用してエンティティを取得するため、プロパティを含めて完全に入力されたリポジトリから返されCustomerTypeます。この場合、これは で発生する可能性があるようCustomerControllerです。

が存在するレイヤーとは別の DAL が必要であることを示し、CustomerController効果的にそれを持っています。これは、リポジトリ インターフェイスを使用する場所です。そのインターフェイスの実装を注入します (または、この場合は、取得します) IoC 実装からの実装) ですが、そのリポジトリの実際の実装は別のレイヤーに存在できます (別のアセンブリであってもかまいません)。これは、分離インターフェイスと呼ばれるパターンです。

個人的には、CustomerController を次のようにリファクタリングします。

public class CustomerController : ControllerBase
{ 
     private ICustomerTypeRepository _customerTypeRepository;
     private ICustomerRepository _customerRepository;

     public CustomerController(ICustomerRepository customerRepository,
        ICustomerTypeRepository customerTypeRepository)
     {
        _customerRepository = customerRepository;
        _customerTypeRepository = customerTypeRepository;
     }

     public ActionResult Index()
     {
         Customer customer 
             = _customerRepository.GetCustomerWithId(customerId); 
             // from where does customerId come?

         IEnumerable<CustomerType> customerTypeList 
             = _customerTypeRepository.GetTypes();

        . . .

     }
}

…そして、リポジトリへのすべての参照をCustomer、他のドメイン エンティティ クラスから削除します。

于 2010-07-09T02:37:29.810 に答える
0

顧客ドメイン モデルを変更して、CustomerTypes のプロパティを含めてみませんか? これにより、CustomerType が呼び出されるたびにリポジトリにアクセスする必要もなくなります。

public class Customer : KeyedObject
{

   public Customer(int customerId)
   {
      _customerRepository.Load(this);

      ICustomerTypeRepository _customerTypeRepository = IoC.Resolve(..);
      _customerTypes = _customerTypeRepository.GetList();
   }

   private ICustomerRepository _customerRepository = IoC.Resolve(..);  

   public virtual string CustomerName {get;set;}
   public virtual int CustomerTypeId {get;set;}

   public virtual string CustomerType
   {
      get
      {
         return _customerTypes.Find(CustomerTypeId);
      }
   }

   private IEnumerable<CustomerType> _customerTypes;
   public virtual IEnumerable<CustomerType> CustomerTypes
   {
      get
      {
          return _customerTypes
      }
   }
}
于 2010-07-06T02:32:34.113 に答える