依赖注入:我应该在哪里注入?谁应该控制它

本文关键字:注入 控制 我应该 在哪里 依赖 | 更新日期: 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?
}

所以,总结一下我的问题:

  1. 以上面显示的方式使用singleton引用(不仅是对容器的引用,而且是对所有容器的引用?(是不是一个坏主意
  2. 我的解决方法正确吗?或者我应该在某个地方使用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反模式。