2012-12-22 3 views
1

Я пытаюсь создать общий слой задач (называемый AppServ в моем проекте) для взаимодействия с моим общим хранилищем. Это мое первое погружение в generics, и у меня возникают проблемы с передачей значения параметру общего метода, который находится в классе Generic:Общие параметры в общем классе

Класс базовых приложений (который наследуется определенным классом сервиса приложения и вызывает общий Repository):

public class BaseAppServ<T> : IBaseAppServ<T> where T : class, IEntity, IAuditStamps, ICompanyFacility, new() 
{ 
    private Repository<T> _repository; 
    private T _viewModel; 
    private AuditStampsViewModel _auditStamps; 

    public BaseAppServ(Repository<T> repository) 
    { 
     _repository = repository; 
     _viewModel = new T(); 
     _auditStamps = new AuditStampsViewModel(); 
    } 

Вот мой конкретный класс AppServ (наследует BaseAppServ)

public class ManageItemsAppServ : BaseAppServ<ManageItemsAppServ>, IEntity, IAuditStamps, ICompanyFacility 
    { 

     public ManageItemsAppServ() 
      : base(CallBaseConstructor()) 
      { 

      } 

      public static Repository<Item> CallBaseConstructor() 
      { 
       return new Repository<Item>(new InventoryMgmtContext()); 
      } 

у меня возникли проблемы в конструкторе или ManageItemsAppServ, в частности, в ((CallBaseConstructor основания)) линии. Это дает ошибку:

Argument 1: cannot convert from 'OTIS.Data.Repository<OTIS.domain.InventoryMgmt.Item>' to 'OTIS.Data.Repository<OTIS.AppServ.InventoryMgmt.ManageItemsAppServ>' 

Я думаю, что я знаю, почему это происходит (потому что, когда я унаследовать BaseAppServ Я указание T типа ManageItemsAppServ и устанавливает тип T для всего класса BaseAppServ ... .right?)

Как я могу переопределить T для вызова конструктора, который ищет тип Respository?

EDIT: Так что я думаю, что нужно добавить второй общий параметр в классе BaseAppServ как (обратите внимание на U, который сдерживает к типу Repository):

public class BaseAppServ<T, U> where U : Repository<U>, IBaseAppServ<T> where T : class, IEntity, IAuditStamps, ICompanyFacility, new() 
    { 
     private Repository<U> _repository; 
     private T _viewModel; 
     private AuditStampsViewModel _auditStamps; 

     public BaseAppServ(Repository<U> repository) 
     { 
      _repository = repository; 
      _viewModel = new T(); 
      _auditStamps = new AuditStampsViewModel(); 
     } 

Это, кажется, правильный путь и Теперь единственная ошибка:

Inconsistent accessibility: constraint type 'OTIS.AppServ.IBaseAppServ<T>' is less accessible than 'OTIS.AppServ.BaseAppServ<T,U>' 

Что есть что-то делать с порядка/синтаксисом объявления класса BaseAppServ. Что это должно быть?

+0

Для второй ошибки, сделать '' IBaseAppServ общественности. –

ответ

1

Вы пытаетесь передать Repository<Item> в качестве аргумента конструктора, где ожидается Repository<ManageItemsAppServ>.

Обратите внимание, что даже если Item наследует от ManageItemsAppServ, это недействительная операция, потому что общие классы не могут быть ко- или контравариантными.

Итак, вкратце, обязательно передайте точный тип или используйте ковариантный интерфейс (зависит ли интерфейс от коварианта от методов на нем).

Edit:

В соответствии с вашим редактирования, вы probaly хотите что-то вроде этого:

public class BaseAppServ<TModel, TItem>: IBaseAppServ<TModel> 
      where TItem : class, IEntity 
      where TModel: ICompanyFacility, new() 
{ 
    private Repository<TItem> _repository; 
    private TModel _viewModel; 
    private AuditStampsViewModel _auditStamps; 

    public BaseAppServ(Repository<TItem> repository) 
    { 
     _repository = repository; 
     _viewModel = new TModel(); 
     _auditStamps = new AuditStampsViewModel(); 
    } 
+0

спасибо за ввод, но мне нужно передать два разных типа дженериков: тип AppServ и тип репозитория. См. Мой отредактированный вопрос, поскольку я думаю, что я на правильном пути. Можете ли вы взять его на финишную прямую :) –

+0

Да, хорошо выглядит - вам нужно сделать 'IBaseAppServ ' public, чтобы использовать его как ограничение 'U'. Кроме того, 'U', вероятно, не должен ограничивать' Repository <> ', поскольку в противном случае у вас будет переменная' Repository > '. Замечание об именах общих аргументов: для лучшей читаемости я обычно называю их «TSomething», когда у меня больше одного. Например, «BaseAppServ ». – Lucero

+0

@ChadRichardson, это сработало? – Lucero

Смежные вопросы