Абстрактный универсальный класс как общие ограничения

#c# #generics #repository #abstract-class

#c# #общие #репозиторий #абстрактный класс

Вопрос:

я пытаюсь создать общий репозиторий для моего объекта поиска и написать это:

 public interface ILookupRepository<T> : 
    IDisposable, 
    ICanGetAll<T>,
    ICanGetById<T, int>
    where T: LookUpObject
{
}
 

ICan... это интерфейс, который определяет детальную работу для репозитория, таким образом, я могу использовать композицию для определения поведения

я хочу ограничить этот интерфейс только для моего объекта поиска, поэтому я использую where T: LookUpObject ограничение

это абстрактный класс:

 public abstract class LookUpObject<TObject, TKeyType> : IKeyedEntity<TKeyType>
    where TObject : class
    where TKeyType : struct
{
    private TKeyType id;
    private string description;
    private bool valid;
    public TKeyType Id
    {
        get { return id; }
        set { id = value; }
    }
    public string Description
    {
        get { return description; }
        set { description= value; }
    }
    public bool Valid
    {
        get { return valid; }
        set { valid= value; }
    }
    protected LookUpObject()
    {           
    }
}
 

но я не знаю, как определить ограничения для моего класса репозитория:
я пытаюсь

 public interface ILookupRepository<T> : 
    IDisposable, 
    ICanGetAll<T>,
    ICanGetById<T, int>
    where T: LookUpObject<T1, TkeyType> where T1: class
        where TkeyType: Type
 

но он не распознает T1 и TkeyType

возможно ли это?

Редактировать

решение @Grax с использованием TkeyType вместо ключа int

 public interface ILookupRepository<T, TkeyType> : 
    IDisposable, 
    ICanGetAll<T>,
    ICanGetById<T, TkeyType>
    where T : LookUpObject<T, TkeyType>
    where TkeyType : struct
 

Комментарии:

1. Это может быть просто так T1 , и TKeyType это должно быть включено ILookupRepository . Не совсем уверен.

Ответ №1:

Я предполагаю, что вы этого хотите. По сути, это ответ Тайкобба с объединением T и T1, но я также думаю, что вы хотите, чтобы TKeyType был struct , основанный на ограничении, которое вы накладываете на свой абстрактный класс, а не на то, чтобы он буквально наследовал от типа «Type».

     public interface ILookupRepository<T, TKeyType> :
        IDisposable,
        ICanGetAll<T>,
        ICanGetById<T, int>
        where T : LookUpObject<T, TKeyType>
        where TKeyType : struct
    {
    }
 

Теперь, если ваш «идентификатор» и ваш «ключ» на самом деле являются одним и тем же фрагментом данных, вы можете даже захотеть, чтобы это было так. Это предполагает, что ключ будет иметь тип «int».

     public interface ILookupRepository<T> :
        IDisposable,
        ICanGetAll<T>,
        ICanGetById<T, int>
        where T : LookUpObject<T, int>
    {
    }
 

Комментарии:

1. предположение почти правильное, может быть, я буду преобразовывать ICanGetById<T, int> в ICanGetById<T, TKeyType> . Завтра на работе я попытаюсь изменить код вопроса

Ответ №2:

Как указано в комментариях Magus, вы должны определить T1 и TKeyType в определении интерфейсов, чтобы вы могли передавать типы.

 public interface ILookupRepository<T, T1, TkeyType> : 
    IDisposable, 
    ICanGetAll<T>,
    ICanGetById<T, int>
    where T: LookUpObject<T1, TkeyType> where T1: class
        where TkeyType: Type
 

Итак, когда вы реализуете интерфейс, укажите, какие типы:

 public MyPersonRepository : ILookupRepository<Person, MyT1Object, MyType>
 

Ваше определение может быть правильным, но, глядя на то, что вы указали в коде, кажется, что вы дублируете T и T1 . Если это так, то избавьтесь от T1 него и просто используйте T вместо этого.

Комментарии:

1. да: T и T1 одинаковы, я подумал, что мне нужно переопределить это