[译]用于企业应用程序的Angular2和WebApi(SPA)-第5部分-DI和IoC-为什么和为什么不?
By robot-v1.0
本文链接 https://www.kyfws.com/applications/angular-webapi-spa-for-enterprise-app-part-di-ioc-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 7 分钟阅读 - 3183 个词 阅读量 0[译]用于企业应用程序的Angular2和WebApi(SPA)-第5部分-DI和IoC-为什么和为什么不?
原文地址:https://www.codeproject.com/Articles/1148437/Angular-WebApi-SPA-for-Enterprise-App-Part-DI-IoC
原文作者:tranthanhtu.vn
译文由本站 robot-v1.0 翻译
前言
In this article, we will why and why not using DI & IoC from my real situation.I did not tell you that DI is not good. From my view, each tech has it own pros and cons. So It is better if we know when we can use which techs for our business.
在本文中,我们将根据我的实际情况,为什么以及为什么不使用DI&IoC,我并没有告诉您DI不好.在我看来,每种技术都有其优点和缺点.因此,最好是知道什么时候可以使用哪种技术开展业务.
系列中的其他文章(Other Articles in the Series)
- 总览(Overview)
- 新增权限(Add new Permission)
- 项目结构(Project structure)
- 多国语言(i18n)(Multi-Languages (i18n))
- DI&IoC-为什么和为什么不?(DI & IoC - Why and Why not?)
- RESTful和Web Api(RESTful & WebApi)
- 管理应用程序生命周期(Manage Application Lifecycle)
- 构建和部署应用程序(Build & Deploy Application)
- 带有Angular 2的TinyERP的新版本(打字稿)(New version of TinyERP with Angular 2 (typescript))
- CQRS:避免企业应用程序中的性能问题(基本)(CQRS: Avoiding performance issues in enterprise app (basic))
- 多个数据存储:扩展存储库(第1部分)(Multiple data-stores: Scale your repository (Part 1))
- 多个数据存储:扩展存储库(第2部分)(Multiple data-stores: Scale your repository (Part 2))
- 使用OWIN的基本身份验证(用户名/密码)(Basic authentication (user name/ password) with OWIN)
介绍(Introduction)
我已经在代码中查看了IoC和DI.(I have looked at IoC and DI in my code.)
希望这可以帮助我们良好地使用IoC和DI.(Hope this can help us use IoC and DI in a good manner.)
我没有告诉你DI不好或IoC比DI好.在我看来,每种技术都有其优点和缺点.因此,最好是知道什么时候可以使用哪种技术开展业务.(I did not tell you that DI is not good or IoC is better than DI. From my view, each tech has it own pros and cons. So It is better if we know when we can use which techs for our business.)
如何获取代码(How to Get the Code)
请在以下位置检查代码(Please check out the code at) https://github.com/techcoaching/TinyERP(https://github.com/techcoaching/TinyERP) .(.)
DI-依赖注入(DI - Dependency Injection)
DI是一种很好的模式,可以帮助我们注入所需的参考:(DI is a good patternt that help us inejcting required references:)
class UserService : IUserService{
private IUserRepository userRepository;
public UserService(IUserRepository userRepository)
{
this.userRepository = userRepository;
}
public void UserRepositoryForSomeActio(){
this.userRepository.<callSomeMethod>();
}
}
如上代码所示,我们看到将自动释放userRepository实例,并且在UserRepositoryForSomeActio方法中也已为我们准备好该实例.(As code above, we see that the userRepository instance will be inejcted automaticly, it was also ready for us in UserRepositoryForSomeActio method.)
这很酷,因为我们可以专注于功能事务.(This is cool, as we can focus on business of function.)
在小型应用程序的上下文中,这很好.让我们看看它在更复杂的应用程序类型中如何(我现在指的是如今在企业应用程序中).(And this is good in the context of small application. Let look how is it in more complext application type (I mean in enterprise application now a day).)
在企业应用程序中,我们有许多核心对象/主要对象,它们对其他对象有很多依赖性.(In Enterprise Application, we have many core object/ major object where it has many dependency on other objects.)
例如:(For example:)订购(Order)对象,我们可以依赖那些较小的对象:(object, we can have dependency on those smaller object:)
- 用户(创建订单的人)(User (who created order))
- 订单行(Orderline)
- 类别(Category)
- 产品(Product)
- 晋升(Promotion)
- 计量单位(UOM)(Unit of Measurement (UOM))
- 科(Branch)
- …(…) 因此,OrderService可能需要为所有依赖项对象注入适当的存储库,如下所示:(So OrderService may require injecting appropriated repository for all of dependency objects as code below:)
class OrderService : IOrderService{
private IUserRepository userRepository;
private IBranchRepository branchRepository;
private IOrderLineRepository orderlineRepository;
private IOrderCategoryRepository orderCategoryRepository;
private IProductRepository productRepository;
private IUOMRepository uomRepository;
public UserService(
IUserRepository userRepository,
IBranchRepository branchRepository,
IOrderLineRepository orderlineRepository,
IOrderCategoryRepository orderCategoryRepository,
IProductRepository productRepository,
IUOMRepository uomRepository,
)
{
this.userRepository = userRepository;
this.branchRepository = branchRepository;
this.orderlineRepository = orderlineRepository;
this.orderCategoryRepository = orderCategoryRepository;
this.productRepository = productRepository;
this.uomRepository = uomRepository;
}
public void UserRepositoryForSomeActio(){
this.userRepository.<callSomeMethod>();
}
}
有几点,我想在这里提出:(There are some points, I want to raise here:)
- 我们需要定义私有变量列表,以保存适当的存储库实例(例如:private Repository uon Repository;)(We need to define the list of private varaibles for holding the instance of appropriated repositories (such as: private IUOMRepository uomRepository;))
- 构造函数有许多参数.(The constructor has many parameters.)
- 构造函数的主体主要将注入的实例分配给私有参数(例如:this.userRepository =userRepository;)(The body of constructor mostly assigns the injected instances to private parameters (such as: this.userRepository = userRepository;)) 这是我的应用程序的真实代码,它对系统的核心实体之一使用了依赖注入:(This is the real code for my application using Dependency Injection for one of the core entities of system:)
namespace App.Services.Impl
{
public class DistributionListService : IDistributionListService
{
private IDistributionListRepository _distributionListRepository;
private IDistributionPeriodRepository _distributionPeriodRepository;
private IGeoRouteNorpostRepository _geoRouteNorpostRepository;
private IUnaddressedOrderRepository _unaddressedOrderRepository;
private IAddressedOrderSummaryPerRouteRepository _addressedOrderSummaryPerRouteRepository;
private IOrderUnaddressedGeoRouteRepository _orderUnaddressedGeoRouteRepository;
private IUserRepository _userRepository;
private IVehicleRepository _vehicleRepository;
private IGeoRoutePackageRepository _routePackageRepository;
private IGeoRoutePackageRouteRepository _geoRoutePackageRouteRepository;
private IDepartmentRepository _departmentRepository;
private IAddressedOrderItemsDeliveryTimeRepository _addressedOrderItemsDeliveryTimeRepository;
private ISortingTimeRepository _sortingTimeRepository;
private IOrderRepository _orderRepository;
private IDepartmentDistributionPeriodExecutionStatusRepository _distributionPeriodExecutionStatusRepository;
private IDistributionPeriodService _distributionPeriodService;
private IGeoRouteHouseholdService _geoRouteHouseholdService;
public DistributionListService(
IDistributionPeriodService distributionPeriodService,
IGeoRoutePackageRouteRepository geoRoutePackageRouteRepository,
IGeoRouteHouseholdService geoRouteHouseholdService,
IDistributionListRepository distributionListRepository,
IDistributionPeriodRepository distributionPeriodRepository,
IGeoRouteNorpostRepository geoRouteNorpostRepository,
IUnaddressedOrderRepository unaddressedOrderRepository,
IAddressedOrderSummaryPerRouteRepository addressedOrderSummaryPerRouteRepository,
IOrderUnaddressedGeoRouteRepository orderUnaddressedGeoRouteRepository,
IUserRepository userRepository,
IVehicleRepository vehicleRepository,
IGeoRoutePackageRepository geoRoutePackageRepository,
IDepartmentRepository departmentRepository,
IAddressedOrderItemsDeliveryTimeRepository addressedOrderItemsDeliveryTimeRepository,
ISortingTimeRepository sortingTimeRepository,
IDepartmentDistributionPeriodExecutionStatusRepository departmentDistributionPeriodExecutionStatusRepository
)
{
//assign those injected to private variables
}
public void SomeMethod(){
// Use 3 of above repositories
}
}
}
在那些服务类的指定方法中,我们仅使用其中一些(大多数在3个左右).(In specified method of those service class, we use just some of them (mostly around 3).)
首先想象一下上面对" DistributionListService"的" SomeMethod"的调用的执行流程.(Let imaging the execution flow of the calling to “SomeMethod” of “DistributionListService” above at the fist time.)
- 系统寻找IDistributionListService的实例(The system looks for instance of IDistributionListService)
- 系统认识到此实现依赖于其他15个存储库.(System recognises that this implementation has dependency on 15 other repositories.)
- 这些存储库将被创建并作为分发列表服务构造函数的参数传递.(Those repositories will be created and passed as parameter of DistributionListService cosntructor.)
- 系统调用" SomeMethod"并消耗其3个用于其业务逻辑.(System invokes “SomeMethod” and consumes 3 of them for its business logic.) 再次检查,我们创建15个存储库的实例.可能需要注意此过程才能为这些存储库创建其他依赖项对象.(Review again, We create instance of 15 repositories. This process may require attention to create other dependency objects to those repositories.)
因此,在执行业务逻辑之前需要创建一长串对象.(Consequence, the long list of objects need to be create before doing the business logic.)
在DI中,我们可以管理实例的生命周期(在Internet上搜索" IoC"或"控制反转"),例如:Single,Transient,…(In DI, we can manage the life time of the instance (search “IoC” or “Inversion Of Control” on internet ), for example: Single, Transient, …)
-
使用Singleton:(With Singleton:)
-
所有注册的类型将创建一次.(All registered types will be create once.)
-
下次,我们可以从内存中取回它.(The next time, We can get it back from memory.) 在企业应用程序的上下文中,我们将有很多类始终存在于服务器的内存中,并且仅部分使用它们.这意味着,我们没有充分利用服务器的内存.(In the context of enterprise application, we will have many classes always existed in memory of server and only part of them frequenly used. It means, we did not use memory of server well enough.)
-
使用瞬态:(With Transient:)
-
所有注册的类型将创建一次.(All registered types will be create once.) 在企业应用程序的上下文中,我们将具有很多依赖项的核心对象/主要对象(如上例所示).因此,创建这种类型的实例需要在子序列中创建并使用其中的许多其他依赖类型.这意味着,我们没有充分利用服务器的功能.(In the context of enterprise application, we will have core objects/ major objects that have many dependency object (as sample above). So creating instance of this type requires a lot of other dependency types created in subsequency and use some of them. It means, we did not use the power of server good enough.)
IoC-控制反转(IoC - Inversion Of Control)
为了改善上述问题,我决定在方法中使用IoC.我的意思是,如果需要,我们将解析并使用适当的存储库.(For improving above issue, I decide to use IoC in method. I mean, we will resolve and use appropriated repositories if need.)
上面的代码可以更改为:(The code above can be changed to:)
namespace App.Services.Impl
{
public class DistributionListService : IDistributionListService
{
public DistributionListService()
{
//oh yeah, I'm free and can be removed from the class now
}
public void SomeMethod(){
IResitory1 repo1 = IoC.Resolve<IResitory1>();
IResitory2 repo2 = IoC.Resolve<IResitory2>();
IResitory3 repo3 = IoC.Resolve<IResitory3>();
// and use above repositories for logic business
}
}
}
在此cde中,我们可以看到:(In this cde, we can see:)
- 看起来更好.(it looks nicer.)
- 我们可以添加或删除未使用的依赖项类型,而不会影响其他代码.(We can add or remove unused dependency types without impact to other code.)
- 我们解决了我们需要使用的东西.所有这些存储库将作为默认值处理.(We resolve what we need to use. all of those repos will be disposed as default.) 因此,以这种方式,我认为我们可以在企业应用程序上下文中在服务器的内存和功能之间取得平衡.(So in this way, I think we can balance between memory and power of server in context of enterprise application.)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
Javascript XML C# .NET IIS Visual-Studio ASP.NET DBA Dev Architect 新闻 翻译