Исключить универсальный тип при использовании наследования - PullRequest
0 голосов
/ 05 апреля 2011

У меня есть этот GenericRepository класс, который я намерен использовать в качестве базового класса для других моих репозиториев.Я строю свои общие методы, как это ...

public class GenericRepository
{
    public void Insert<TEntity>(TEntity entity) where TEntity : class
    {
        var collection = GetCollection<TEntity>();
        collection.Save<TEntity>(entity);
    }
}

Теперь мой вопрос ...

Можно ли наследовать GenericRepository таким образом, что у вас нетявно включить универсальный тип при вызове каждого метода?Например, если бы у меня был UserRepository : GenericRepository, я мог бы написать:

var repo = new UserRepository();
repo.Insert(user);
// Instead of
repo.Insert<User>(user);

Ответы [ 4 ]

1 голос
/ 05 апреля 2011
public class UserRepository : GenericRepository<User> {}
1 голос
/ 05 апреля 2011

C # уже позволит вам опустить универсальный тип, если тип не является неоднозначным.Однако он не будет обеспечивать проверку во время компиляции, что тип является пользователем;для этого вам нужно сделать параметр типа частью репозитория следующим образом:

public class GenericRepository<TEntity> where TEntity : class
{
    public void Insert(TEntity entity)
    {
        var collection = GetCollection<TEntity>();
        collection.Save<TEntity>(entity);
    }
}

public sealed class UserRepository : GenericRepository<User> { ... }
1 голос
/ 05 апреля 2011

Вам не нужно ничего делать. Это просто работает, если user действительно имеет тип User, потому что компилятор выведет тип.

Но вы действительно должны изменить свою иерархию классов на это, то есть использовать универсальный параметр для уровня класса:

public class GenericRepository<TEntity> where TEntity : class
{
    public void Insert(TEntity entity) 
    {
        var collection = GetCollection<TEntity>();
        collection.Save<TEntity>(entity);
    }
}

public class UserRepository : GenericRepositry<User>
{
    //...
}

Справочная информация:

Когда вы расширите свой репозиторий, вы увидите, почему:

public class GenericRepository
{
    public void Insert<TEntity>(TEntity entity) where TEntity : class
    {
        var collection = GetCollection<TEntity>();
        collection.Save<TEntity>(entity);
    }

    public void Delete<TEntity>(TEntity entity) where TEntity : class
    {
         // ...
    }
}

Этот код был бы возможен, но не имел бы никакого смысла, поскольку каждый экземпляр хранилища должен отвечать только за один тип:

var genericRepository = new GenericRepository();
genericRepository.Insert(new User());
genericRepository.Delete(new Comment());
0 голосов
/ 05 апреля 2011

Наследование не требуется для получения этого эффекта.Компилятор C # имеет функцию, называемую вывод типа, которая позволяет выводить тип параметров универсального метода во многих случаях.Например, следующее будет хорошо скомпилировано.

var repository = new GenericRepository();
User u = ...;
repository.Insert(u);

Здесь тип, передаваемый в Insert, равен User, и, следовательно, компилятор может легко сделать вывод, что TEntity должен быть User в этом сценарии и позволяет пропустить параметр.

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