web-dev-qa-db-ja.com

クラスライブラリのIoC。どこにbootstrap

他のコンポーネントで再利用できるクラスライブラリを使用しています。このクラスライブラリでは、依存関係の注入にUnityを使用しています。このクラスライブラリでは、テストプロジェクトを作成します。呼び出し元は、テストプロジェクトも取得します。私が不確かなことの1つは、バインディングの場所です。これをクラスライブラリに組み込む必要がありますか、それとも呼び出し側アプリケーションから行う必要がありますか?

30
Patrick

これは興味深い問題です。エントリポイントのない再利用可能なアセンブリを依存関係注入する方法を教えてください。 本当に他の人の答えを見てみたいです。

依存性注入は、エントリポイントアセンブリの責任です。しかし、それぞれDIを必要とするクラスやアセンブリがたくさんある場合は、一部のクラスやアセンブリではそれらが省略され、タスクが面倒になる可能性があります。

ソリューションワン

設定より規約を使用します。クラスFooの実装IFooなどのルールに固執します。多くのDIフレームワークには、慣例を使用してそれをセットアップする手段があります。

ソリューション2

上記の解決策はすべての問題を解決するわけではありません。時々、注入の設定をパラメータ化する必要があるからです。これが私が問題を解決した方法です(特に[〜#〜] mef [〜#〜]でロードされたアセンブリの場合、これはAutoFac用です):

作成されたインターフェースIIocInstaller whereコンテナー(またはビルダーが渡される)

public interface IIocInstaller
{
    void Setup(ContainerBuilder builder);
}

DIを必要とするアセンブリにフラグを付けるアセンブリ属性を作成:

[AttributeUsage(AttributeTargets.Assembly)]
public class ExportAssemblyAttribute : Attribute
{
}

各アセンブリで、DIをセットアップするクラスを作成します:

[Assembly: ExportAssembly]
namespace This.That
{

    [Export(typeof(IIocInstaller))]
    public class IocInstaller : IIocInstaller
    {
        public void Setup(ContainerBuilder builder)
        {
            ....
        }
    }
}

次に、エントリポイントに、Assembly属性を持つすべての読み込まれたアセンブリ(MEFされたものを含む)を調べ、IIocInstallerを実装する型を探して、それらに対してSetupを呼び出す共通コードがあります。

8
Aliostad

答えが選ばれたことは知っていますが、Unityの一部を見落としていると思います。これは特定のUnityの質問だったので、IUnityContainerExtensionConfiguratorを実装するUnityContainerExtension基本クラスを指摘しました。これは、APIライブラリが拡張されて、コンテナを所有するエントリポイントアプリケーションが、ライブラリがコンテナに正しく登録されていることを簡単に確認できるようにし、API所有者が何を登録し、どうやって。

これは、この目的でMicrosoftエンタープライズライブラリによって使用されます。

Loggingライブラリを簡単なものとして使用します。

public class LoggingUnityExtension : UnityContainerExtension
{
    protected override void Initialize()
    {
        Container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());
    }
}

次に、エントリポイントアプリケーションがこれを行います。

public class Bootstrapper : UnityBootstrapper
{
    protected override void ConfigureContainer()
    {
        base.ConfigureContainer();

        Container.AddNewExtension<EnterpriseLibraryCoreExtension>();
        Container.AddNewExtension<LoggingUnityExtension>();
        // ... 
    }

    // ...
}

これで、エンタープライズライブラリとロギングライブラリのAPIが登録されました。これは、このメソッドを使用するエントリポイントアプリケーションにとって非常に簡単です。これは、ライブラリ開発者が目標として持つべきものです。

25
Rodney S. Foley

呼び出し元のアプリケーションから行うと、呼び出し元のアプリケーションの負担が大きくなります。初期化を省略して問題が発生する可能性を残します。

静的コンストラクターなど、クラスライブラリで実行します。

2

OK Project.Iocという名前のライブラリを作成します。ここにUnityをインストールします。他のレイヤーをIocライブラリに参照します。そしてIoc Libraryをプレゼンテーション層に。 UnityHelperという名前のクラスを作成します。

/// <summary>
/// Bind the given interface in request scope
/// </summary>
public static class IocExtensions
{
    public static void BindInRequestScope<T1, T2>(this IUnityContainer container) where T2 : T1
    {
        container.RegisterType<T1, T2>(new HierarchicalLifetimeManager());
    }

    public static void BindInSingletonScope<T1, T2>(this IUnityContainer container) where T2 : T1
    {
        container.RegisterType<T1, T2>(new ContainerControlledLifetimeManager());
    }
}

/// <summary>
/// The injection for Unity
/// </summary>
public static class UnityHelper
{

    public static IUnityContainer Start()
    {
        var container = BuildUnityContainer();

        DependencyResolver.SetResolver(new Unity.Mvc4.UnityDependencyResolver(container));

        return container;
    }

    /// <summary>
    /// Inject
    /// </summary>
    /// <returns></returns>
    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();

        // register all your components with the container here
        // it is NOT necessary to register your controllers

        // Database context, one per request, ensure it is disposed
        container.BindInRequestScope<IMVCForumContext, MVCForumContext>();
        container.BindInRequestScope<IUnitOfWorkManager, UnitOfWorkManager>();

        //Bind the various domain model services and repositories that e.g. our controllers require         
        container.BindInRequestScope<ITopicService, TopicService>();

        container.BindInRequestScope<ITopicTagRepository, TopicTagRepository>();

        //container.BindInRequestScope<ISessionHelper, SessionHelper>();

        return container;
    }
}

MvcForumプロジェクトを調べてください。 MvcForm.Iocクラスライブラリがあります。ライブラリは他のレイヤー参照を取得します。 UnityHelperという名前のクラスは1つだけです。

https://github.com/leen3o/mvcforum

これがあなたが探しているワットであることを願っています。

0