2014-10-23 3 views
1

Я разрабатываю приложение MVC, использую Unity для IoC. Мое приложение в основном состоит из слоя пользовательского интерфейса, уровня обслуживания и уровня репозитория.Рекомендации по IoC в сложном слое обслуживания

Мой типичный контроллер:

public class TestController : Controller 
    { 
     private ITestService testServ; 

     public TestController(ITestService _testServ) 
     { 
      testServ= _testServ; 
     } 

    public ActionResult Index() 
    { 
     testServ.DoSomething(); 
     return View(); 
    } 
} 

Ничего необычного, каждый из моих контроллеров не объект службы впрыскивается. Таким образом, мои объекты уровня обслуживания выполняют сложные бизнес-правила, объединяющие информацию из разных хранилищ. Используя IoC, я нахожу, что мои конструкторы выглядят чересчур сложными, но поскольку служба требует доступа ко многим репозиториям, я не вижу никакого способа обойти это.

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

public class TestService : ITestService 
    { 
     private ITransactionRepository transRepo; 
     private IAccountRepository accountRepo; 
     private ISystemsRepository sysRepo; 
     private IScheduleRepository schRepo; 
     private IProfileRepository profileRepo; 

     public TestService(ITransactionRepository _transRepo; 
          IAccountRepository _accountRepo; 
          ISystemsRepository _sysRepo; 
          IScheduleRepository _schRepo; 
          IProfileRepository _profileRepo) 
     { 
      transRepo = _transRepo; 
      accountRepo = _accountRepo; 
      sysRepo = _sysRepo; 
      schRepo = _schRepo; 
      profileRepo = _profileRepo; 
     } 

     public DoSomething() 
     { 
      //Implement Business Logix 
     } 
    } 

Несколько моего объект службы слоя требуется 10 или более хранилищ. В моем хранилище используется Entity Framework, где каждый класс репозитория предоставляет таблицу в базовом хранилище данных.

Я ищу советы по наилучшей практике в ситуации, описанной выше.

+0

Ищите советы по IoC или на контейнерах DI (Unity - это позже)? – Carsten

+0

BTW: если ваша служба «Service» имеет много зависимостей, она, вероятно, делает * много * (S в SOLID) - возможно, вы можете разделить службу на ее настоящие обязанности - скорее всего, вы можете дать результаты лучше имени, чем * Сервис * тоже;) – Carsten

ответ

1

Вот некоторые шаги, чтобы упростить (и уменьшение) зависимости:

  1. Split обслуживание на отдельные услуги и ввести их в контроллере. Это уменьшит количество зависимостей сервисов. Недостатком является то, что вам нужно будет добавить больше зависимостей к вашим контроллерам. Следующим шагом является разделение контроллеров, когда они становятся сложными. Вспомните о Single Responsibility Principle.

  2. Посмотрите на Bounded Context схеме: вы могли бы попытаться группы лиц, которые часто приходит вместе в одном контексте и внедрить этот контекст в службу вместо инъекций десятки хранилищ:

    public class TestService : ITestService 
    { 
        private readonly ITestData testData; // represents a bounded context 
    
        public TestService(ITestData testData) 
        { 
         this.testData = testData; 
        } 
    
        public void DoSomething() 
        { 
         this.testData.Transactions.Add(...); //It gives you access to Transactions repository 
        } 
    } 
    
2

You создали сервисный уровень, так что он действует как фасад для базовых репозиториев. Этот подход является хорошей практикой для предоставления фасада клиенту с грубым API. Клиентам не нужно беспокоиться о базовых репозиториях.

Служба сама по себе имеет сложный конструктор из-за того, как выполняется DI. Другой подход заключается в использовании абстрактного заводского шаблона на уровне сервиса и введении инжектора сеттера. Эта сложность создания новых хранилищ переносится в отдельный класс, собственный завод. Например:

Вы можете установить хранилища тестовой службы следующим образом вместо конструктора

public class TestService : ITestService 
{ 
    private ITransactionRepository transRepo = DataAccess.transRepo; 
    private IAccountRepository accountRepo = DataAccess.accountRepo; 
    private ISystemsRepository sysRepo = DataAccess.sysRepo; 
    private IScheduleRepository schRepo = DataAccess.schRepo ; 
    private IProfileRepository profileRepo = DataAccess.profileRepo; 
} 

Ниже приведен пример интерфейса для завода

public interface IRepoFactory 
{ 
    ITransactionRepository TransRepo {get;} 
    IAccountRepository AccountRepo {get;} 
    ISystemsRepository SysRepo {get;} 
    IScheduleRepository SchRepo {get;} 
    IProfileRepository ProfileRepo {get;} 
} 

Ниже приведен пример конкретной фабрики, которая будет обновлять все репозитории.

public class EfFactory : IRepoFactory 

{ 

    public ITransactionRepositry TransRepo { return new TransactionRepository();} 

    public IAccountRepository AccountRepo {return new AccountRepository();} 

    public ISystemsRepository SysRepo {return new SystemRepository();} 

    public IScheduleRepository SchRepo {return new SchRepository();} 

    public IProfileRepository ProfileRepo {return new ProfileRepository();} 

} 

Ниже фабричный метод, который будет возвращать бетонный завод (в вашем случае, это будет EF Factory)

public class RepoFactories 
{ 
    public static IRepoFactory GetFactory(string typeOfFactory) 
    { 
     return (IRepoFactory)Activator.CreateInstance(Type.GetTypetypeOfFactory) 
    } 
} 

Абстрактная фабрика со статическими методами в новое и вернуть хранилище объекты

// Пример: factoryName = MyProject.Data.EFFactory (Это может быть добавлено в вашем web.config или app.config)

Public static class DataAccess 
{ 
    private static readonly string DbfactoryName= ConfigurationManager.AppSettings.Get("factoryName"); 
    private static readonly IRepoFactory factory = RepoFactories.GetFactory(DbfactoryName); 

    public static ITransactionRepositry transRepo 
    { 
     get {return factory.TransRepo;} 
    } 
    public static IAccountRepository accountRepo 
    { 
     get {return factory.AccountRepo;} 
    } 
} 
Смежные вопросы