Vadimyan
@Vadimyan
Программист C#

Автоопределение Generic-типов внутри Generic (Get<TEntity>() where TEntity: IEntity<TId>)?

Привет, народ!
У меня вечно возникают проблемы с generic.
Есть следующая структура классов:
class Entity<TId> where TId : struct 
{ 
    public virtual TId Id { get; set; } 
}

interface IRepository<T, in TId> where T : Entity<TId> where TId : struct 
{ 
    T Get(TId id); 
    IList<T> GetAll(); ... 
}

class RepositoryProvider
{
        public IRepository<TEntity, TId> GetRepository<TEntity, TId>() where TEntity : Entity<TId> where TId : struct
        { ... }
}


Мне не нравится необходимость при вызове GetRepository указывать оба дженерик-параметра. Ведь когда я подставляю первый параметр, то из него можно извлечь информацию о втором. Класс не может дважды наследовать Entity с разными TId, значит информация однозначная.
Я хочу иметь возможность написать:
provider.GetRepository<Department>();
вместо
provider.GetRepository<Department, int>();

Но при попытке объявить метод следующим образом:
public IRepository<TEntity, TId> GetRepository<TEntity>() where TEntity : Entity<TId> where TId : struct

возникает очевидная ошибка компиляции "The type or namespace name 'TId' could not be found (are you missing a using directive or an assembly reference?)".

Есть ли способ обойти это ограничение? Устроила бы рефлексия или Emit, но как их тут применить не представляю. Прошу прощения за сумбурный способ изложения мыслей.
  • Вопрос задан
  • 3013 просмотров
Решения вопроса 1
Nirvano
@Nirvano
Может чем поможет:

RepositoryProvider provider = new RepositoryProvider();
dynamic repo = provider.GetRepository<Entity<int>>();
List<Entity<int>> list = repo.GetAll();
Entity<int> entry = repo.Get(10);


interface Entity { }

class Entity<TId> : Entity
    where TId : struct
{
    public virtual TId Id { get; set; }
}

interface IRepository<T, in TId>
    where T : Entity<TId>
    where TId : struct
{
    T Get(TId id);
    IList<T> GetAll();
}

class Repo<T, TId> : IRepository<T, TId>
    where T : Entity<TId>
    where TId : struct
{
    public T Get(TId id)
    {
        return default(T);
    }

    public IList<T> GetAll()
    {
        return new List<T>();
    }
}

class RepositoryProvider
{
    public dynamic GetRepository<TEntity>()
        where TEntity : Entity
    {
        Type genericParam = typeof(TEntity).GetGenericArguments()[0];
        return Activator.CreateInstance(typeof(Repo<,>).MakeGenericType(typeof(TEntity), genericParam));
    }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы