3

我刚开始使用 DDD,并且对对象和存储库的接口有疑问。假设我有以下对象

public interface IPerson { ... }

public class Student 
{
    double gpa;
    ...
}

public class Teacher
{
    double salary; ...
}

然后我也有两个存储库,例如

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

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

我的问题是,假设我有一个名为 people 的 IPerson 对象列表,有没有一种方法可以让我做类似 repository.Save(persons) 的事情?无需使用反射来确定 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>();
    }
}

因此,当您派生TeacherStudentPerson<T>您传递通讯员T时,例如

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

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

这将使您能够在没有反射的情况下使用 List 或切换功夫。

于 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

两种可能的方法。

一、特定于域类型的接口

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 回答