c# - 复杂服务层 IoC 的最佳实践

标签 c# asp.net-mvc design-patterns inversion-of-control

<分区>

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

我的典型 Controller 是:

public class TestController : Controller
    {
        private ITestService testServ;

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

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

没有什么不寻常的,我的每个 Controller 都注入(inject)了一个服务对象。因此,我的服务层对象执行复杂的业务规则,聚合来自许多不同存储库的信息。通过使用 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 ,其中每个存储库类在底层数据存储中公开一个表。

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

最佳答案

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

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

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

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

下面是一个工厂接口(interface)的例子

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

关于c# - 复杂服务层 IoC 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26524303/

相关文章:

c# - 我是否应该在共享进程生命周期的对象上调用 dispose?

asp.net-mvc - jquery表单提交成功与失败回调

ios - 在 UITableViewCell 和 UICollectionViewCell 之间共享代码

design-patterns - 基于用户权限启用用户界面元素的设计模式?

design-patterns - 数据验证/多条件的最佳设计模式

c# - System.Collections.Queue<T>、线程、锁定和同步

c# - 如何在不指定 SharpPDF 中每个段落的确切坐标的情况下创建段落?

ASP.NET Identity - IUser 接口(interface)中的 UserName 和 Id 有什么区别?

asp.net-mvc - 嵌套对象的远程 ViewModel 验证不起作用

c# - 如何在 c# 中查看对服务引用的传入响应的完整 SOAP 响应(包括 header )?