1

インターフェイスを実装する具体的な ViewModel がリポジトリに渡され、ViewModel オブジェクトが読み込まれるパターンを使用していますが、インターフェイスのみを使用しています。これにより、リポジトリが少し重くなりますが、リポジトリをさまざまなシナリオで再利用できます。たとえば、具体的な実装は MVC ViewModel である場合もあれば、インターフェイスを実装する asp.net Page である場合もあります。このインターフェイスでは、各プロパティの set アクセサーが、たとえばテキスト ボックスのように、実際に GUI に値を入力します。インターフェイスの実装はマッピングとして機能し、コピーの余分な手順を排除します。AutoMapper を広範囲に使用し、現在このパターンにさらされているので、私はこれを好みます。

public interface IPerson
{
  int Id{set};
  string Name{set};
  string Address{set};
}

public class PersonRepository
{
   GetPerson(int id, IPerson person)
   {
      //query...    
      person.Id = result.Id;      
      person.Name = result.Name;
      person.Address = result.Address;    
   }
}

//...controller action
PersonViewModel person = new PersonViewModel();
rep.GetPerson(5, person);

ただし、ここでトリッキーな部分が発生します。ViewModel は、インデックス ページやドロップ ダウンのようなもの、またはネストされた子オブジェクトのセットを表示するために、アイテムのコレクションを必要とする場合があります。リポジトリはインターフェイスをインスタンス化できないため、ファクトリとして提供します。しばらく共分散と格闘した後、あらゆる種類のコレクションを公開することを断念し、コレクション アイテムの作成と追加の両方を行うメソッドにたどり着きました。

public interface IPerson
{
  //...
  IJobRole CreateAndAddJobRole();    
}

public class PersonViewModel:IPerson
{
  //collection not part of the interface
  ICollection<JobRoles> JobRoles {get;set;} //= new List<JobRoles> in constructor

  public CreateAndAddJobRole()
  {
    role = new JobRole();
    JobRoles.Add(role);
    return role;
  }
}

public class PersonRepository
{
   GetPerson(int id, IPerson person)
   {
      //...
      foreach(var result...)
      {
        IJobRole role = person.CreateAndAddJobRole();
        role.SomeProperty = //...
      }
   }
}

明らかに、ジョブロールを処理するリポジトリを実際にコレクションに投入するリポジトリにするでしょう。異なるリポジトリが扱うデータの入力を担当するように、実際にはより詳細なインターフェイスを使用することになるでしょう。ViewModel は単に複数のインターフェイスを実装します。つまり、改善の余地があることは認識していますが、コレクションの問題に対処するための良いアイデアがないため、ここにいます.

この設計の利点の 1 つは、リポジトリによって悪用される可能性のあるコレクションが公開されないことです。誰がコレクション自体をインスタンス化する責任があるのか​​、誰がそれを設定するのかについて推測することは決してありません。または、getter しかない場合、リポジトリがコレクションを取得し、それを無効な方法で変更する可能性があります。チームはパターンを知っているため、これらはめったに発生しないと思いますが、誰もが介入しないように覚えておく必要がある落とし穴があるのではなく、落とし穴がまったくないことは常に良いことです.

このままでは、ちょっとモヤモヤした感じ。

具体的な型をインスタンス化してコレクションに追加する機能をどのように設計/公開しますか?そうするメソッドがインターフェイスの知識しか持っていない場合?

4

1 に答える 1

1

あなたの最善の策は、各インターフェースを汎用化し、コレクションの型を渡すことです。例えば:

public interface IPerson<TJob> where TJob : IJobRole
{
  ICollection<TJob> JobRoles {get;set;} 
  void AddJobRole(TJob role);
}

public JobRole : IJobRole
{
}

public class PersonViewModel:IPerson<JobRoles>
{
  //collection is now part of the interface
  ICollection<JobRoles> JobRoles //= new List<JobRoles> in constructor

  public void AddJobRole(JobRoles role)
  {
    JobRoles.Add(role);
  }
}

public class PersonRepository
{
   GetPerson(int id, IPerson<JobRoles> person)
   {
      //...
      foreach(var result...)
      {
        person.AddJobRole(new JobRole { 
            SomeProperty = //... 
            SomeOther = //...
        }
      }
   }
}

もちろん、これは をIPerson<>呼び出すときに必要なのタイプを知っていることを前提としていますGetPerson()。ただし、そこで処理する必要がある場合はIPerson、さらに問題が発生します。

于 2012-10-11T17:44:53.203 に答える