1

免責事項: コンパイラを使用せずに記述されたコードは、構文エラーを破棄する必要があります。:)

自分のしていることが「正しい」のか疑問に思っています。

現在、静的メソッドを持つ 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>();
}

Manager のメソッドは次のようになります。

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. 上記の方法でシングルトン参照を使用するのは悪い考えですか?
  2. 私は正しく解決していますか?それとも、BuildUp をどこかで使用する必要がありましたか? スタートアップ プロジェクトのコードから Resolve を呼び出す必要がありましたか?

お時間をいただきありがとうございます!

4

1 に答える 1

2

依存関係は、コンストラクターで静的コンテナーまたはシングルトン コンテナーを使用するのではなく、最上位層のクラスから順にカスケードで解決する必要があります。

このリンクを確認してください。

アプリが依存関係を解決するためのパイプラインへのフックを (コントローラーの場合と同様に) 提供しない場合Unity.Mvc3、最良のアプローチは、ManagerUnity を介して (トップ レイヤー クラス) クラスを解決し (最初に登録する必要があります)、DI コンテナーにIRepository. これにより、静的/シングルトン コンテナーを 1 か所に保持し、制御下に置くことができます。アプリ内の他のレイヤーは、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 の適切な構成により、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) を使用する場合でも。コンテナーは、サービスロケーターのアンチパターンを回避するために最上位のレイヤー クラスをロードするためだけに使用されます。

于 2013-03-04T13:47:07.933 に答える