【问题标题】:use decorator pattern with unity container (for singletons)将装饰器模式与统一容器一起使用(用于单例)
【发布时间】:2017-05-17 07:47:23
【问题描述】:

我有 2 个接口,一个继承自另一个。 对于基接口,我有一个单例实现,对于子接口,我有一个装饰器单例实现(装饰基实现)

现在,如果基接口被注入(或解析)到其他客户端,它们会得到基实现,而不是装饰器(如果它们依赖于子接口,它们只会得到装饰器)

我想要的是,装饰器实现应该被注入到每个客户端,但基础实现仍然需要构建并注入到装饰器单例中。

我该如何设置?

using System;
using Microsoft.Practices.Unity;

public interface IProvider
{
    int GetValue();
}

public interface ITracker : IProvider
{       
}

public class Provider : IProvider
{
    public int GetValue()
    {
         Console.WriteLine("provider");
         return 0;
    }
}

追踪器:

public class Tracker : ITracker
{
    private readonly IProvider provider;

    public Tracker(IProvider provider)
    {
         this.provider = provider;
    }

    public int GetValue()
    {
        Console.WriteLine("tracker");
        return provider.GetValue();
    }
}

程序:

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();

        container.RegisterType<IProvider, Provider>(
            new ContainerControlledLifetimeManager());
        container.RegisterType<ITracker, Tracker>(
            new ContainerControlledLifetimeManager());

        // want to get Tracker singleton instance here 
        var provider = container.Resolve<IProvider>(); 

        // want to get Tracker singleton instance here
        var tracker = container.Resolve<ITracker>(); 
    }
}

【问题讨论】:

  • 您希望所有 ITracker 实例都具有相同的 IProvider 实例吗?
  • 只有一个提供者实例和一个跟踪器实例(均注册为单例)跟踪器将提供者作为依赖项。但是客户端应该获得单例跟踪器,无论它们依赖于 IProvider 还是 ITracker
  • 因此您只想将 IProvider 注入到 Tracker 实现中。如果 IProvider 依赖于任何其他类,它应该获得 ITracker?
  • @Scrobi:完全正确。装饰器是唯一应该获得提供者的组件,所有其他组件都应该获得装饰器。

标签: c# dependency-injection unity-container


【解决方案1】:

我不是 Unity 方面的专家,但这就是我的想法:

由于 Tracker 是一个单例,您可以将 IProvider 作为构造函数参数传入。然后,您将 IProvider 和 ITracker 都设置为解析为 Tracker 的实例。虽然我仍然不得不将 IProvder 投射到 ITracker。

var container = new UnityContainer();
container.RegisterType<IDependency, Dependency>();   
container.RegisterType<IProvider, Provider>("Provider");


container.RegisterType<ITracker, Tracker>
(
    new ContainerControlledLifetimeManager(),
      new InjectionConstructor(
        new ResolvedParameter<IProvider>("Provider")
));

container.RegisterType<IProvider, Tracker>
(
    new ContainerControlledLifetimeManager(),
      new InjectionConstructor(
        new ResolvedParameter<IProvider>("Provider")
));

var p = container.Resolve<IProvider>() as ITracker;
var t = container.Resolve<ITracker>();

【讨论】:

  • 问题在于这个解决方案我必须自己创建Provider实例,但我希望容器为我创建它(因为在真实系统中,Provider还会有其他依赖项)
  • 要使上述工作正常运行,您必须在创建提供者实例之前建立依赖关系。
  • 您可以为映射注册一个名称,然后在将参数注入构造函数时使用它。
猜你喜欢
  • 2012-12-17
  • 1970-01-01
  • 2020-02-25
  • 1970-01-01
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多