免责声明:没有编译器编写的代码,您应该丢弃任何语法错误。 :)
我想知道我在做什么是“正确的”。
目前,我有一个带有静态方法的Manager类。这些方法都在我的Repository类上调用一个方法(例如,Manager.Get将调用Repository.Get,依此类推)。
将注入Repository实现!
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?
}
所以,总结一下我的问题:
感谢您的时间!
答案 0 :(得分:2)
依赖关系应该从顶层类向下级联,而不是在构造函数中使用静态或单例容器。
选中link。
如果你的应用程序没有提供任何钩子进入管道以解决依赖关系(如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的prorper配置,我只需要解决ClasificationManagement,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反模式。