Dependencies should be resolved in cascade down from the top layer classes, not using static or singleton container in constructors.
Check this link.
If your app does not provide any hook into the pipeline to resolve the dependencies (as Unity.Mvc3
does with controllers) the best aproach is resolve the Manager
(your top layer class) class through Unity (you must register it first) and let the DI container inject IRepository
. This alows you to keep the static/singleton container in one place and keep things under control. No other layer in your app should know anything about DI container.
An example of resolving complete dependency graph could be the next piece of code:
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
With the prorper configuration of Unity in XML or runtime I just need to resolve ClasificationManagement and Unity do the dirty work of resolving all dependecy chain.
//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")
For Unity config I like xml configuration because you can change the dependencies and no compilantion is needed. Just include this function somewhere in the initialization logic of your app.
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
A XML config should looks like:
<?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>
I hope this example hepls you to understand the phylosophy of DI. Even when I use a static container (ServiceLocator); the container is used just to load top level layer classes to avoid servicelocator antipattern.