Шаблон репозитория с .NET 1.1

Каков типичный подход к использованию шаблона репозитория с .NET 1.1 (C#)?

Я ищу что-то вроде этот вопрос о переполнении стека, за исключением того, что в .NET 1.1 у меня нет дженериков, поэтому я просто хочу посмотреть, возможно ли это (я уверен, что да), и как это обычно делается .


person Matthew Groves    schedule 08.07.2009    source источник


Ответы (2)


Это очень возможно, но вам нужно либо не использовать общий интерфейс, либо делать много кастингов. Использование интерфейса...

public interface IRepository
{
    public object Get(int id); // or object id
    public void Save(object obj);
}

public class CustomerRepository : IRepository
{
    public object Get(int id) { // implementation }
    public void Save(object obj) { // implementation }
}

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

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

public class CustomerRepository
{
    public Customer Get(int id) { // implementation }
    public void Save(Customer entity) { // implementation }
}

public class EmployeeRepository
{
    public Employee Get(int id) { // implementation }
    public void Save(Employee entity) { // implementation }
}

Отредактировано для добавления: я перечитал связанный ответ. Последний полный абзац сбивает меня с толку, но я могу немного расширить использование DI. В большинстве случаев не имеет смысла использовать DI для внедрения «общего» (в данном случае означает производного от общего интерфейса) репозитория. В дополнение к общим методам репозиторий будет иметь методы, специфичные для сущностей, такие как GetCustomersWithPastDueAccounts. Вы можете определить ICustomerRepository с помощью этого метода и реализовать его в CustomerRepository. Затем вы можете использовать внедрение зависимостей для внедрения CustomerRepository во время выполнения. В этом нет ничего плохого, но, по моему опыту, довольно редко у вас будет несколько реализаций репозитория, поэтому в этом мало смысла.

person Jamie Ide    schedule 08.07.2009
comment
Но с вашим вторым подходом я не потеряю возможность вводить зависимости? - person Matthew Groves; 08.07.2009
comment
Вы всегда можете сделать ручную инъекцию зависимостей. Но вы правы, вы не сможете использовать структуру DI для внедрения зависимостей. Я отредактирую свой ответ и добавлю больше объяснений. - person Jamie Ide; 09.07.2009
comment
В общем, для каждого репозитория есть интерфейс, который можно использовать для внедрения зависимостей. Для 10 сущностей, 10 интерфейсов, не менее 10 реализаций. Звучит правильно? - person Matthew Groves; 09.07.2009
comment
Звучит правильно. Сделайте его даже сотней сущностей, и оно будет считаться корпоративным приложением. С помощью дженериков вы можете использовать один конкретный класс в качестве репозитория для объекта, у которого нет никаких дополнительных функций, кроме тех, которые определены в базовом интерфейсе. - person Jamie Ide; 09.07.2009

если я что-то неправильно понял, принятый ответ на вопрос, который вы связали, не использует дженерики. Он определяет интерфейс и использует термин «общий» для обозначения того, что интерфейс не привязан напрямую к какой-либо конкретной таблице в модели.

person Geoff    schedule 08.07.2009
comment
Я не думаю, что это так, но если это так, как будут выглядеть сигнатуры этих 7 функций в IEntityRepository? - person Matthew Groves; 08.07.2009
comment
Он имеет в виду реализацию репозитория, использующую интерфейс IRepository‹TEntity›. - person Enrico Campidoglio; 08.07.2009