Приведите конкретный экземпляр класса к интерфейсу, который использует дженерики - PullRequest
1 голос
/ 01 июня 2011

Вот мой конкретный репозиторий, производный от абстрактного базового класса

public class DepartmentRepository : RepositoryBase<Department>, IDepartmentRepository

public abstract class RepositoryBase<T> : IRepository<T> where T : class, IPersistantBusinessObject

Вот мои интерфейсы

public interface IDepartmentRepository : IRepository<Department>

public interface IRepository<T> where T : IPersistantBusinessObject

public interface IPersistantBusinessObject { ... }

А вот мои сущности

public class Department : BusinessObjectBase

public abstract class BusinessObjectBase : IPersistantBusinessObject

Как преобразовать мой DepartmentRepository в общий IRepository?

DepartmentRepository rep = new DepartmentRepository();
(IRepository<IPersistentBusinessObject>)rep; // this doesn't work

Идеи?Если вам интересно, это приложение asp.net MVC3, использующее шаблон репозитория.Я над архитектором интерфейсов?Как мне теперь использовать универсальный репозиторий?

Спасибо.

РЕДАКТИРОВАТЬ: Вот мой интерфейс IRepository.На вопрос о том, почему мне нужно привести в IRepository, это на самом деле только для того, чтобы я мог использовать метод «SaveChanges», потому что я хочу перехватывать любые исключения из базы данных и обрабатывать их обычным способом.

public interface IRepository<T> where T: IPersistantBusinessObject
{
    IQueryable<T> Retrieve();
    T Retrieve(int id);
    IQueryable<T> RetrieveActiveAndInActive();
    T RetrieveActiveAndInActive(int id);
    void Add(T domainObject);
    void SaveChanges();
    void Delete(T domainObject);
    void Delete(int id)
 }

Ответы [ 3 ]

3 голосов
/ 01 июня 2011

Что вы пытаетесь сделать здесь?Я не могу вспомнить ситуацию, в которой вы хотели бы привести к IRepository<IPersistentBusinessObject>.Какой код зависит от какой абстракции?

Я бы обычно ожидал, что другой код будет зависеть от абстракции IDepartmentRepository, и вообще не вижу варианта использования для IRepository<T> или даже IPersistentBusinessObject,Опять же, если вы можете найти вариант использования для кода, который зависит от этой абстракции, то они ценны;в противном случае, YAGNI .

(Кстати, это одна из причин, почему разработка через тестирование полезна. Вы можете выяснить, какие абстракции вам нужны, написав юнит-тесты и посмотрев, какие классынужно поддразнивать, чтобы изолировать тестирование определенной функциональности, вместо того, чтобы просто смутно абстрагировать все в интерфейсы, потому что вам сказали, что они лучше конкретных типов. Начните с конкретных типов, и когда ваши тесты вынуждают вас извлечь интерфейс, это подходящее время!)


Действительно, речь идет о ковариантности родовых типов .Это должно работать, если вы скажете

public interface IRepository<out T> where T : IPersistantBusinessObject
0 голосов
/ 07 сентября 2011

Как предполагает Даниэль, вы не можете привести его к IRepository, потому что вы определили, что интерфейс IRepository существует только в сочетании с другим типом T. Таким образом, IRepository как интерфейс не существует.

Если вы хотите использовать интерфейс «IRepository», то он должен быть автономным без зависимости от типа.

Возможно, вам нужны два интерфейса, один из которых реализует базовую функциональность, которую вы хотите в IRepository, а другой - общие методы для типа T. Например,

<!-- language: lang-c# -->
public interface IRepository
{
  SaveChanges()
...
}

public interface IRepositoryFor<T> where T : IPersistantBusinessObject
{
  T GetFirst(); // or whatever
...
}
0 голосов
/ 01 июня 2011

Вам нужно привести его к IRepository<Department>.

DepartmentRepository происходит от RepositoryBase<Department>, который реализует IRepository<Department>.

Возможно, вы захотите взглянуть на co и контрвариантность ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...