web-dev-qa-db-ja.com

WindowsサービスでのUnityDI、可能ですか?

定期的な操作を行うためにWindowsサービスを開発していますが、Unityを使用して別のライブラリからクラスを挿入できますか?

サービスの[依存関係]属性で使用し、Windowsサービス開始のエントリポイントにコンポーネントを登録したいと思います。

例:

static class Program
{
    static void Main()
    {
         ServiceBase[] ServicesToRun;
         UnityConfig.RegisterComponents();
         ServicesToRun = new ServiceBase[] 
         { 
                new EventChecker()
         };
         ServiceBase.Run(ServicesToRun);
   }
}


public static class UnityConfig
{
    public static void RegisterComponents()
    {
        UnityContainer container = new UnityContainer();
        container.RegisterType<IEventBL, EventBL>();
    }
}

public partial class EventChecker : ServiceBase
{
    private Logger LOG = LogManager.GetCurrentClassLogger();

    [Dependency]
    public Lazy<IEventBL> EventBL { get; set; }

    protected override void OnStart(string[] args)
    {
        var events = EventBL.Value.PendingExecution(1);
    }
}

このシナリオでは、EventBLは常にnullであるため、単一性の[依存関係]によって解決されません。それを機能させる方法はありませんか?

ありがとう!


見つかった解決策:

答えを書いた後、私は可能な解決策を見つけました。サービスクラスを作成するためにコンテナのメソッドを構築するために呼び出すことは機能します:

    UnityContainer container = new UnityContainer();
    UnityConfig.RegisterComponents(container);

    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[] 
    { 
        container.BuildUp(new EventChecker())
    };
    ServiceBase.Run(ServicesToRun);

他の解決策を知っている場合は、それを共有してください:)

12
juan25d

UnityのようなDIコンテナは、Windowsサービスのオブジェクトグラフを作成するためにも使用できます。一般に、コンストラクターインジェクションを使用することをお勧めします。これにより、 一時的な結合 が防止され、コードがDIライブラリ自体に依存するのを防ぎます(コンポーネント間の強い結合を防止しようとしているため、DIライブラリに依存する必要があるのは非常に皮肉です)。 。

さらに、単にコンテナにサービスを解決させる必要があります。つまり、サービスを手動で更新するのではなく、コンテナーから新しいインスタンスを要求します。

ServicesToRun = new ServiceBase[] 
{ 
    container.Resolve<EventChecker>()
};

ただし、EventCheckerは一度解決され、アプリケーションの期間中保存されることに注意してください。これにより、事実上シングルトンになり、その依存関係はすべてシングルトンになります。したがって、代わりに、ServiceBase実装をコンポジションルートの一部にし、時間が発生するたびにコンテナから新しいインスタンスを解決することをお勧めします。

public class EventChecker : ServiceBase
{
    private static IUnityContainer container;

    public EventChecker(IUnityContainer container) {
        this.container = container;
    }

    public void SomeOperationThatGetsTriggeredByATimer() {
        using (this.container.StartSomeScope()) {
            var service = this.container.Resolve<IEventCheckerService>();

            service.Process();
        }
    }
}
21
Steven