Так я обычно делаю в своих реализациях.
Общий интерфейс IEntityRepository, который определяет вашу базовую структуру CRUD. В моих реализациях я определяю следующие члены:
- Вставить
- Обновление
- Удалить
- Получить
- GetPaged
- GETALL
- Find (этот использует построитель предикатов для построения предложения where)
Я создаю другой интерфейс IMyentityRepository, который наследует IEntityRepository. Это позволяет мне добавлять любые элементы, связанные с сущностью, и при этом иметь возможность использовать DI, когда мне это нужно. Затем я создаю свой запечатанный класс MyentityRepository, который наследует IMyentityRepository и реализует все члены.
Когда вы используете Dependency Injection, вы можете зарегистрировать свой интерфейс (IMyentityRepository) для конкретного типа MyentityRepository.
В моем случае, я на самом деле не закончил. Я создал сервисный слой поверх хранилища, чтобы инкапсулировать его и показать его в более общем виде. Например, допустим, вы хотите создать учетную запись для своего пользователя, что может потребовать больше усилий, чем просто создание записи в базе данных. В вашей службе у вас будет элемент с именем CreateUser (), который может вызывать несколько членов репозитория в своей реализации.
Мой уровень обслуживания построен так же, как и мой уровень хранилища. У меня есть IEntityService для общих членов CRUD, IMyentityService для элементов, специфичных для сущности, и MyentityService для реализации. Класс MyentityService может потребовать экземпляр IMyentityService (вы можете внедрить его с выбранной платформой IoC). Уровень обслуживания также может выполнять проверку и любую бизнес-логику. Я делаю проверку в контроллерах. Ну, технически, я вызываю его своими контроллерами и получаю результат, который затем могу записать в ModelState.
Надеюсь, это немного помогло.