3

私は DDD を始めたばかりで、オブジェクトとリポジトリのインターフェースに関して質問があります。次のオブジェクトがあるとします

public interface IPerson { ... }

public class Student 
{
    double gpa;
    ...
}

public class Teacher
{
    double salary; ...
}

次に、次のような2つのリポジトリもあります

public class StudentRepository :IRepository { public void Save(Student) }

public class TeacherRepository :IRepository { public void Save(Teacher) }

私の質問は、persons という名前の IPerson オブジェクトのリストがあるとします。リフレクションを使用して IPerson が実際にどのタイプであるかを把握する必要はありません。

私は現在別のクラスを持っています

PersonRepository :IRepository 
{
     public void Save(IPerson person)
     {
          if(Person is Student)
          {
               new StudentRepository.Save(person as Student);
          }
          else if(Person is Teacher)
          { ....}
      }
}

次に、personRepository.Save(persons); を呼び出すことができます。ただし、これは物事を構造化するための最適な方法とは思えません。このデザインを改善するにはどうすればよいですか?

ありがとう

編集:

私が探しているのは、person という IPerson オブジェクトを受け取ったとします。私は必ずしもそれがどのような実装であるかを知りません.repository.Save(person)を呼び出して、正しいリポジトリを呼び出したいだけです. リフレクションである種の switch ステートメントを使用せずにこれを行う方法はありますか?

4

3 に答える 3

4

汎用リポジトリの使用を検討する

class Repository<T> :IRepository<T>
{
     public void Save(T entity)
     {
         ...
     }
}

使用法

IRepository<Student> repo1 = new Repository<Student>();
repo1.Save(new Student());

IRepository<Teacher> repo2 = new Repository<Teacher>();
repo2.Save(new Teacher());


次に、IoC コンテナと DI を使用して、リポジトリを作成する代わりに渡すことができます。

上位では、mainメソッドまたはglobal.asaxで言う

IRepository<Student> studentRepo = IoC.Current.Resolve<IRepository<Student>>();

後でデータを保存する必要があるクラスで、IRepository<Student> studentRepoコンストラクターに渡します

class Foo
{
    private IRepository<Student> repo

    Foo(IRepository<Student> repo)
    {
        this.repo = repo;
    }

    public void Save(Student s)
    {
        repo.Save(s);
    }
}

編集

保存操作をIPerson<T>

class Person<T> : IPerson<T>
{
    private IRepository<T> repo;

    Person(IRepository<T> repo)
    {
        this.repo = repo;
    }

    public void Save()
    {
        repo.Save<T>();
    }
}

したがって、次のように派生Teacherして元StudentからPerson<T>通信者を渡すとT

class Student : Person<Student>
{
    private IRepository<Student> repo;

    Person(IRepository<Student> repo):base(repo)
    {
       ...
    }    
}

これにより、リフレクションなしでリストを操作したり、カンフーを切り替えたりすることができます。

于 2012-08-14T20:52:52.060 に答える
3

C#ジェネリックを使用したメソッドを潜在的に持つことができます

interface Repository<TEntity> where TEntity : class {

    void Save(TEntity entity);    
}

しかし、ジェネリック (C# ジェネリックではなく、一般化されたもの) リポジトリを使用することはお勧めしません。リポジトリ インターフェイスは、ドメイン駆動型であり、エンティティに固有である必要があります。Greg Young によるこの記事を検討してください。

エンティティのインターフェイスがある理由も明確ではありません ( IPerson)。インターフェースは通常、アプリケーションの継ぎ目で作成されます。IPerson を複数実装する予定はありますか?

于 2012-08-14T20:50:27.423 に答える
1

2つの可能なアプローチ。

まず、ドメインタイプに固有のインターフェース

interface IStudentRepository
interface ITeacherRepository
class StudentRepository : IStudentRepository
class TeacherRepository : ITeacherRepository

第二に、ジェネリックインターフェース

interface IRepository<T>
class StudentRepository : IRepository<Student>
class TeacherRepository : IRepository<Teacher>
于 2012-08-14T20:55:54.653 に答える