Общее наследование интерфейса и реализация класса для шаблона репозитория - PullRequest
5 голосов
/ 24 января 2011

Я немного прочитал об ограничениях и пытаюсь реализовать их в своем шаблоне хранилища.

Я хочу что-то вроде ниже, но не могу заставить его скомпилировать.

 public interface IRepository<T>
 {
    void GetAllData<T>();
 }

 //This needs to inherit from IRepository
 //T has to be a model class
 //V has to be a class that implements IEmployeeRepo
 public interface IEmployeeRepo<T, V> where V : EmployeeRepo where T : class : IRepository<T>
 {
    void DoSomethingEmployeeRelated();
 }

 //Dont think this inheritance is correct
 public class EmployeeRepo<Employee, this> : IEmployeeRepo
 {


 }

 //My example model class
 public class Employee
 {
     public string Name {get;set;}
 }

Ответы [ 3 ]

18 голосов
/ 24 января 2011

Не уверен, почему у вас есть два параметра типа в репозитории - в чем смысл?

* Вот классический пример репозитория .NET с использованием Generics: *

* Во-первых, интерфейс репозитория: *

public interface IRepository<T> where T : class
{
   T FindSingle(Expression<Func<T,bool>> predicate);
   IQueryable<T> FindAll(); // optional - matter of preference
   void Add(T entity);
   void Remove(T entity);
}

* Во-вторых, универсальная реализация репозитория (например, EF): *

public abstract class GenericRepository<T> : IRepository<T>
{
   private IObjectSet<T> _ObjectSet; // get this in via DI (for example)

   public T FindSingle(Expression<T,bool>> predicate)
   {
      return _ObjectSet.SingleOrDefault(predicate);
   }

   // you can figure out how to do the other implementation methods
}

* Затем, Конкретный репозиторий (у вас должно быть по одному на корень совокупности, а также интерфейс для каждого конкретного репозитория, детализирующий конкретные методы): *

public EmployeeRepository : GenericRepository<Employee>, IRepository<Employee>
{
   // all regular methods (Find, Add, Remove) inherited - make use of them
   public Employee FindEmployeeByName(string name)
   {
      return FindAll().SingleOrDefault(x => x.Name == name);
      // or you could do: return FindSingle(x => x.Name == name);    
   }
}

Использование:

IRepository<Employee> repository = new EmployeeRepository<Employee>();

Не думайте, что вам нужно сходить с ума от дженериков - единственное, что вам нужно, - это ограничить использование репозитория сущностью, которая заключена в капсулуРепозиторий.

Я просто использую where T : class.

Другое использование where T : IDomainAggregate или подобное, чтобы наложить ограничения на фактический тип объекта, который разрешен.

5 голосов
/ 24 января 2011

В этой ситуации у меня обычно есть базовый класс репо, который реализует IRepository <> и типизирован для базового класса Model.

public interface IRepository<T> where T : IModel
 {
    void GetAll<T>();
    void GetById<T>(int id);
 }    

 public interface IEmployeeRepo<T> : IRepository<T> where T : IModel
 {
    void DoSomethingEmployeeRelated();
 }

 public class BaseRepo : IRepository<T> where T : IModel
 {

    public void GetAll<T>()
    {

    }

    public void GetById<T>(int id)
    {

    }
 }


 public class EmployeeRepo : BaseRepo<Employee>,  IEmployeeRepo<Employee>
 {
    public void DoSomethingEmployeeRelated()
    {

    }

 }

 //My example model class
 public class Employee : IModel
 {
     public int Id {get;set;}
     public string Name {get;set;}
 }
1 голос
/ 24 января 2011

Попробуйте это;

public interface IRepository<T>
 {
    void GetAllData<T>();
 }

 //This needs to inherit from IRepository
 //T has to be a model class
 //V has to be a class that implements IEmployeeRepo
 public interface IEmployeeRepo<T, V> : IRepository<T> where V : EmployeeRepo where T : class
 {
    void DoSomethingEmployeeRelated();
 }

 //Dont think this inheritance is correct
 public class EmployeeRepo : IEmployeeRepo<Employee, EmployeeRepo>
 {
    public void DoSomethingEmployeeRelated()
    {

    }

    public void GetAllData<Employee>()
    {

    }
 }

 //My example model class
 public class Employee
 {
     public string Name {get;set;}
 }
...