Unity依赖关系无法解决任务问题

时间:2015-03-17 16:35:14

标签: c# asp.net dependency-injection task unity-container

我不确定如何解决目前的情况。我试图创建一个任务:

public class whatever
{
    [Dependency]
    public IReportingBL ReportingBL { get; set; }

    private whatever()
    {
    ...task factory creation, etc.
    }

    private readonly static Lazy<whatever> _instance = new Lazy<whatever>(() => new whatever());

    public static whatever Instance { get { return _instance.Value; }

    public Task GetStuff()
    {
        return _taskFactory.StartNew(() =>
        {
            return ReportingBL.Method1;
        });
    }
}

报告BL没有得到解决。如果我在线程中创建了一个新的ReportingBL实例,那么它下面的图层就不会得到解决。

如何在这种情况下团结一致?

1 个答案:

答案 0 :(得分:2)

您正在应用Singleton Design Pattern。这是一种皱眉的模式,被一些人视为反模式。在依赖注入术语中,Singleton模式可以被认为是Ambient Context,这是一种在依赖注入的上下文中几乎不应该使用的模式。

单例设计模式与依赖注入不兼容,因为:

  • 使用依赖注入,应用程序的Composition Root可以控制创建实例并缓存它们;不是实例本身。
  • 让消费者依赖公共Instance字段,导致消费者违反依赖性倒置原则,并禁止该实例被替换,嘲笑,装饰或截获。这会妨碍您的应用程序的可维护性和可测试性。

此外,在您的代码中,我没有看到对Unity DI框架的任何调用。请记住,DI容器不是一个神奇的工具,它将允许类“由他们自己”初始化。在您的代码中,您直接新建whatever; Unity没有参与其中。 Unity(或任何DI库)只有在控制对象时才能自动连接对象。换句话说,您必须为Unity调用container.Resolve<whatever>()来构建您的实例。

虽然您可以从container.Resoolve工厂委托中调用Lazy<T>,但这会强制该类依赖容器本身,通常称为Service Locator anti-pattern。< / p>

相反,我建议您对设计进行以下更改:

  1. 使用构造函数注入而不是属性注入。财产注入导致Temporal Coupling
  2. 使组合根和容器负责连接对象图。
  3. 远离Singleton设计模式;请改用容器的Singleton Lifestyle。
  4. 这导致以下代码:

    public interface IWhatever
    {
        Task GetStuff();
    }
    
    public class Whatever : IWhatever
    {
        private readonly IReportingBL reportingBL;
    
        public whatever(IReportingBL reportingBL) {
            this.reportingBL = reportingBL;
        }
    
        public Task GetStuff() {
            return _taskFactory.StartNew(() => {
                return ReportingBL.Method1;
            });
        }
    }
    
    // Some consumer of whatever
    public class MyController : Controller
    {
        private readonly IWhatever whatever;
    
        public MyController(IWhatever whatever) {
            this.whatever = whatever;
        }
    
        public ActionResult Index() {
            return View(this.whatever.GetStuff());
        }
    }
    

    在撰写根目录中,您可以按如下方式配置类:

    var container = new UnityContainer();
    
    container.RegisterType<IReportingBL, ReportingBL>(
        new ContainerControlledLifetimeManager());
    container.RegisterType<IWhatever, Whatever>(
        new ContainerControlledLifetimeManager());
    
    var controller = container.Resolve<MyController>();
    
    controller.Index();