0

Я создаю API-интерфейс библиотеки классов, который обертывает бизнес-логику и доступ к базе данных SQL Server через Entity Framework 6.Шаблон проектирования для точки входа API?

Я разработал ее с использованием модуля работы и шаблонов репозитория. Целью является упрощение использования и модульного тестирования.

Бизнес-логика и проверка выполняются на сервисном уровне. Я не буду использовать контейнер IOC, потому что чувствую, что это усложнит использование API .

Проект имеет 15 хранилищ и услуг

Текущий дизайн выглядит следующим образом:

Service Layer A -> Единица работы -> Repository А и или B
Service Layer B -> Единица работа -> Repository B или а и ...
...

public class ServiceA : IServiceA, IService 
{ 
    private readonly IUnitOfWork unitOfWork; 

    public AssetService(IUnitOfWork unitOfWork) 
    { 
     this.unitOfWork = unitOfWork; 
    } 

    ... 

    public IList<DomainObjectA> GetAll() 
    { 
     return unitOfWork.RepositoryA.GetAll(); 
    } 

    public void Dispose() 
    { 
     unitOfWork.Dispose(); 
    } 

    ... 
} 

public class UnitOfWork : IUnitOfWork 
{ 
    private readonly MyDbContext context = new MyDbContext(); 
    private IRepositoryA repositoryA; 
    private IRepositoryB repositoryB; 
    ... 

    public IRepositoryA RepositoryA 
    { 
     get { return repositoryA = repositoryA ?? new RepositoryA(context); } 
    } 

    public IRepositoryB RepositoryB 
    { 
     get { return repositoryB = repositoryB ?? new RepositoryB(context); } 
    } 

    ... 

    public void Save() 
    { 
     context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     context.Dispose(); 
    } 
} 

public class RepositoryA : Repository, IRepositoryA 
{ 
    public RepositoryA(MyDbContext context) 
     : base(context) {} 

    public IList<DomainObjectA> GetAll() 
    { 
     return context.tblA.ToList().Select(x => x.ToDomainObject()).ToList(); 
    } 

    ... 
} 

Поскольку это API, который должен быть использован в других проектах, мне нужен хороший и «честно» легко т o использовать интерфейс для пользователя, который использует API. Из-за этого модуль UnitOfWork создается в этом «общедоступном интерфейсе» между пользователем и уровнем сервиса, см. Ниже.

Я также считаю, что лучше всего использовать инструкцию using в API, чтобы db-контекст располагался правильно и сразу после каждого вызова службы.

Я начал с использованием прокси-шаблона для этого: Примера:

public class ProxyA : Proxy, IServiceA 
{ 
    public IList<DomainObjectA> GetAll() 
    { 
     using (var service = GetService<ServiceA>()) 
      return service.GetAll(); 
    } 
    ... 
} 

public abstract class Proxy 
{ 
    protected T GetService<T>() where T : IService 
    { 
     return (T)Activator.CreateInstance(typeof(T), new object[] { new UnitOfWork()}); 
    } 
} 

Но это потребовало бы мне создать прокси-сервер для каждого сервиса. Я мог бы, конечно, пропустить интерфейс службы в прокси и создать общий прокси-сервер, который обрабатывает все службы.

Я также рассмотрел шаблон «Фасад», но не могу решить, какой шаблон использовать для этого конкретного сценария.

Мои вопросы:
Является ли это хорошим подходом или есть какие-либо другие шаблоны проектирования, которые позволят решить эту проблему?

Также должна быть одна публичная точка входа API или несколько, сгруппированных по какой-либо бизнес-логике?

ответ

0

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

Что касается шаблона прокси-сервера, это ваш вызов, если вы хотите его использовать или нет. Как вы говорите, вам нужно создать код плиты котла, чтобы создать его для каждой службы. Если это возможно, если вы хотите использовать его только для того, чтобы скрыть вызов службы db, или вы предпочитаете добавлять эту строку кода каждый раз, когда вы вызываете эту услугу (и убедитесь, что вы делаете это, чтобы избежать утечек). Также вы можете подумать, возможно, вам понадобится добавить дополнительные функции в Proxy в будущем, что добавит дополнительный вес для создания прокси-опции.

Что касается одной точки входа или нескольких, я бы создал ServiceA, ServiceB, ServiceC и т. Д. (Так несколько), сгруппированных для доменов бизнес-логики.Как правило, вы будете иметь между 5-20 (только приблизительным числом, чтобы дать представление о масштабах)

Вы можете захотеть пересмотреть принцип интерфейса сегрегации, которая поддерживает эту идею

http://en.wikipedia.org/wiki/Interface_segregation_principle

+0

Так вы говорите, создать меньше сервисов (groupd по бизнес-логике) вместо одного для каждого репозитория, а затем сохранить шаблон прокси (один прокси для каждой службы) как фронт api? Я думаю, что мне нравится этот подход лучше, чем создание жирного класса фасадов, который содержит все доступные методы api ... – ThePike

+0

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