依赖注入:我应该在哪里注入?谁应该控制它
本文关键字:注入 控制 我应该 在哪里 依赖 | 更新日期: 2023-09-27 18:00:51
免责声明:在没有编译器的情况下编写的代码,应该丢弃任何语法错误。:(
我想知道我所做的是"正确的"。
目前,我有一个带有静态方法的Manager类。这些方法分别调用我的Repository类上的一个方法(例如Manager.Get将调用Repository.Get,依此类推(。
将注入存储库实现
Manager有一个静态字段,该字段将一个单例实例引用到自身,以及对存储库实例的引用。
static Manager _me = new Manager();
[Dependency]
public IRepository Repo;
注意:这就是我目前的解决方式!我需要反馈
在经理Ctor中,我解决了依赖
public Manager()
{
// Feedback would be nice on this as well!
// I have a singleton reference to the container,
// being set from the startup project.
Repo = Singleton.UnityContainer.Resolve<IRepository>();
}
经理的方法如下:
public static MyObject Get(int id)
{
return _me.Repo.Get(id);
}
在我的主程序(例如控制台应用程序(中,我将注册我的实现。
static void Main(string[] args)
{
var container = Singleton.UnityContainer = new UnityContainer();
// The implementation to inject, could change over time
// to a MSSQL or MySQL, who knows? Hence the DI!
var myXmlRepo = new XmlRepository("C:'My.xml");
// Register the instance
container.RegisterInstance(myXmlRepo);
container.RegisterInstance<IRepository>(myXmlRepo, new ContainerControlledLifetimeManager()); // Why do I need to register TWICE?
}
所以,总结一下我的问题:
- 以上面显示的方式使用singleton引用(不仅是对容器的引用,而且是对所有容器的引用?(是不是一个坏主意
- 我的解决方法正确吗?或者我应该在某个地方使用BuildUp吗?我应该从启动项目代码中调用Resolve吗
感谢您抽出时间!
依赖关系应该从顶层类级联解析,而不是在构造函数中使用静态或单例容器。
检查此链接。
如果你的应用程序没有在管道中提供任何钩子来解决依赖关系(就像Unity.Mvc3
对控制器所做的那样(,最好的方法是通过Unity解析Manager
(你的顶层类(类(你必须先注册它(,并让DI容器注入IRepository
。这允许您将静态/单例容器放在一个地方,并控制一切。应用程序中的任何其他层都不应该知道DI容器的任何信息。
解决完整依赖关系图的一个例子可能是下一段代码:
Public Class ClasificationManagement //application layer service, top layer class
Implements IClasificationManagement
Private _servicio As IClasificacionesService //inject domain serice for bussines
Private _repositorio As IClasificationRepository //inject repository for perisitence
Public Sub New(ByVal servicio As IClasificacionesService, ByVal repositorio As IClasificationRepository)
_servicio = servicio
_repositorio = repositorio
End Sub
Public sub SwapDescrition(ByVal clasificationOrigenID As String, ByVal clasificationDestinoID As String) Implements IClasificationManagement. SwapDescrition
//code using domain services and repositories
End sub
Public class ClasificacionesService
implements IClasificacionesService
private _tracer as ITracer //inject tracer to service domain
public sub new(tracer as ITracer)
_tracer = tracer
end sub
//not relevant code using ITracer
End Class
使用XML或运行时中Unity的按比例配置,我只需要解决冲突管理问题,Unity就可以解决所有依赖链的问题。
//resolve manager
manager = ServiceLocator.Current.GetInstance(Of IClasificationManager)()
//use manager, all dependencies (bussines service, repositories, tracers) were injected by Unity
manager.SwapDescrition("123-ABC", "456-DEF")
对于Unity配置,我喜欢xml配置,因为您可以更改依赖项,不需要编译。只需在应用程序的初始化逻辑中的某个位置包含此功能即可。
Imports Microsoft.Practices.Unity
Imports Microsoft.Practices.Unity.Configuration
Imports Microsoft.Practices.ServiceLocation
Private Sub InitServiceLocator()
Dim container As IUnityContainer = New UnityContainer()
container.LoadConfiguration() //read xml config
//container.RegisterType<Of ...>(...) //config in runtime
Dim provider = New UnityServiceLocator(container)
ServiceLocator.SetLocatorProvider(Function() provider)
End Sub
XML配置应该如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IClasificationManagement" type="AppPrincipal.IClasificationManagement, AppPrincipal" />
<alias alias="IClasificationRepository" type="X509ValDAL.IClasificationRepository, X509ValDAL" />
<alias alias="IClasificacionesService" type="Entidades.IClasificacionesService, Entidades" />
<alias alias="IUnitOfWork" type="X509ValDAL.IUnitOfWork, X509ValDAL" />
<alias alias="ObjectContext" type="System.Data.Objects.ObjectContext, System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<alias alias="ClasificationManagement" type="AppPrincipal.ClasificationManagement, AppPrincipal" />
<alias alias="ClasificationRepository" type="X509ValDAL.ClasificationRepository, X509ValDAL" />
<alias alias="ClasificacionesService" type="Entidades.ClasificacionesService, Entidades" />
<alias alias="UnitOfWork" type="X509ValDAL.UnitOfWork, X509ValDAL" />
<alias alias="X509VALEntities" type="Entidades.X509VALEntities, Entidades" />
<assembly name="AppPrincipal" />
<assembly name="X509ValDAL" />
<assembly name="Entidades" />
<assembly name="System.Data.Entity" />
<namespace name="AppPrincipal" />
<namespace name="X509ValDAL" />
<namespace name="Entidades" />
<namespace name="System.Data.Objects" />
<container>
<register type="IClasificationManagement" mapTo="ClasificationManagement">
<constructor>
<param name="servicio">
<dependency/>
</param>
<param name="repositorio">
<dependency/>
</param>
</constructor>
</register>
<register type="IClasificationRepository" mapTo="ClasificationRepository">
<constructor>
<param name="uow">
<dependency/>
</param>
</constructor>
</register>
<register type="IClasificacionesService" mapTo="ClasificacionesService" />
TODO: Inject ITracer
<register type="ObjectContext" mapTo="X509VALEntities" />
<register type="IUnitOfWork" mapTo="UnitOfWork" >
<constructor>
<param name="context">
<dependency />
</param>
</constructor>
</register>
</container>
</unity>
我希望这个例子能帮助你理解DI的哲学。即使我使用静态容器(ServiceLocator(;容器仅用于加载顶层类,以避免servicelocator反模式。