【问题标题】:Updating a dependency injected singleton更新依赖注入的单例
【发布时间】:2018-11-13 18:48:50
【问题描述】:

我在运行时生成一个单例

public void ConfigureServices(IServiceCollection services)
{
    var applications = Utils.generateApplications()
    services.AddSingleton<ApplicationModel[]>(applications);
    services.AddMvc();
}

我以后如何使用全新的ApplicationModel[] 更新这个注入ApplicationModel[] 的依赖项。我的应用程序中有一个功能,用户可以使用它来触发应用程序上的数据刷新,但是如何更新底层注入的 Singleton,以便所有未来的注入都使用更新后的应用程序?我有一个函数Utils.generateApplications(),它获取最新的应用程序列表并返回ApplicationModel[]。如果有意义的话,我如何用一个新对象覆盖旧注入的 Singleton 以注入到未来的调用中?

我有一些代码:

public void UpdateData()
{
    var applications = Utils.generateApplications()
    //How do I set applications to replace the injected singleton for all future injections?
}

【问题讨论】:

  • 似乎在ApplicationModel[] 周围放置一个包装器会容易得多,使用您的数组作为属性之一创建一个新类。然后你的所有代码都得到相同的单例,但你可以随意更新属性(只是要注意线程安全)

标签: c# .net-core asp.net-core-2.0


【解决方案1】:

您应该使用额外的间接层。我认为最简单的方法是使用抽象工厂。定义一个类似这样的接口:

interface IApplicationModelFactory
{
    public ApplicationModel[] GetModel();
}

使用更新模型所需的方法(或多个方法)定义第二个接口:

interface IApplicationModelUpdate
{
    void UpdateModel();
}

然后,您可以将 ApplicationModel[] 注册从单个实例更改为作用域并委托给工厂:

var modelFactory = new ApplicationModelFactory();
services.AddSingleton<IApplicationModelFactory>(provider => modelFactory);
services.AddSingleton<IApplicationModelUpdate>(provider => modelFactory);
services.AddScoped<ApplicationModel[]>(provider => modelFactory.GetModel());

IApplicationModelUpdate 注入到更新模型的类型中,将ApplicationModel[] 注入到使用它的类型中。这样做的好处是,为同一请求解析的所有类型都将获得模型的一致视图,即使它在处理该请求的过程中发生了变化。

您也可以将IApplicationModelFactory 注入消费者代码,但我认为直接注入模型更好。使用工厂可能会导致不同位的代码在同一请求期间看到不同的模型。模型的可变性也是消费者代码不必担心的一个实现细节。

【讨论】:

    【解决方案2】:

    我不会用这种方式来玩依赖注入。相反,注入一个工厂,并编写返回正确实例所需的任何逻辑。

    简单工厂:

    interface IApplicationModelFactory
    {
        ApplicationModel[] Model { get; }
    }
    
    class ApplicationModelFactory : IApplicationModelFactory
    {
        public ApplicationModel[] Model { get; set; }
    }
    

    注册:

    services.AddSingleton<IApplicationModelFactory>
    (
        new ApplicationModelFactory[] { Model = util.generateApplications() }
    )
    

    接收注入的类:

    class Foo
    {
        protected readonly IApplicationModelFactory _factory;
    
        public Foo(IApplicationModelFactory injected)
        {
            _factory = injected;
        }
    
        protected ApplicationModel[] => _factory.Model;
    
        public void Bar()
        {
            DoSomethingWithModel(this.ApplicationModel);
        }
    }      
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-10
      • 2011-02-21
      • 2015-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-10
      相关资源
      最近更新 更多