复杂服务层中IoC的最佳实践

我正在开发一个MVC应用程序,我正在使用Unity for IoC。 我的应用程序基本上由UI层,服务层和存储库层组成。

我的典型控制器是:

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,其中每个存储库类都在底层数据存储中公开一个表。

我正在寻找有关所描述情况的最佳实践的一些建议。

以下是一些简化(和减少)依赖项的步骤:

  1. 将服务拆分为单独的服务并将其注入控制器。 这将减少服务的依赖性数量。 缺点是您需要向控制器注入更多依赖项。 分裂控制器变得复杂时,下一步就是它们。 记住单一责任原则 。

  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 } } 

您已创建了一个服务层,以便它充当底层存储库的外观。 这种方法是一种很好的做法,可以使用粗API为客户端提供外观。 客户端不必担心底层存储库。

由于DI的完成方式,服务本身现在具有复杂的构造函数。 另一种方法是在服务层使用抽象工厂模式并执行setter注入。 新的存储库的这种复杂性被移动到一个单独的类中,它自己的工厂。 例如:

您可以按如下方式设置测试服务的存储库,而不是构造函数

 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工厂)

 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;} } }