我在运行时生成一个单例
public void ConfigureServices(IServiceCollection services)
{
var applications = Utils.generateApplications()
services.AddSingleton<ApplicationModel[]>(applications);
services.AddMvc();
}
我以后如何用全新的
ApplicationModel[]
更新这个注入的依赖项ApplicationModel[]
。我的应用程序中有一个功能,用户可以使用该功能来触发应用程序上的数据刷新,但是如何更新底层注入的单例,以便所有未来的注入都将使用更新的应用程序?我有一个函数 Utils.generateApplications()
,它可以获取最新的应用程序列表并返回 ApplicationModel[]
。如果有意义的话,如何用新对象覆盖旧的注入单例以注入到将来的调用中?
我有一些代码:
public void UpdateData()
{
var applications = Utils.generateApplications()
//How do I set applications to replace the injected singleton for all future injections?
}
您应该使用额外的间接层。我认为最简单的方法是使用抽象工厂。定义一个像这样的接口:
interface IApplicationModelFactory
{
public ApplicationModel[] GetModel();
}
使用更新模型所需的方法定义第二个接口:
interface IApplicationModelUpdate
{
void UpdateModel();
}
然后,您可以将
ApplicationModel[]
注册从单一实例更改为范围并委托给工厂:
var modelFactory = new ApplicationModelFactory();
services.AddSingleton<IApplicationModelFactory>(modelFactory);
services.AddSingleton<IApplicationModelUpdate>(modelFactory);
services.AddScoped<ApplicationModel[]>(provider =>
provider.GetRequiredService<IApplicationModelFactory>().GetModel());
将
IApplicationModelUpdate
注入到更新模型的类型中,并将 ApplicationModel[]
注入到使用模型的类型中。这样做的优点是,为同一请求解析的所有类型都将获得模型的一致视图,即使它在处理该请求的过程中发生了变化。
你也可以将
IApplicationModelFactory
注入消费者代码中,但我认为直接注入模型更好。使用工厂可能会导致不同的代码在同一请求期间看到不同的模型。模型的可变性也是消费者代码不必担心的实现细节。
我不会那样胡闹依赖注入。相反,注入一个工厂,并编写返回正确实例所需的任何逻辑。
简易工厂:
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);
}
}
在 .Net 7 中,让客户端订阅事件操作并收到模型更改通知。
程序.cs
...
builder.Services.AddSingleton<IApplicationModel>(new ApplicationModel());
...
应用程序模型.cs
...
public event Action SummaryChangedEvent;
...
组件.razor
...
@inject IApplicationModel applicatinModel
...
@code {
...
protected override async Task OnInitializedAsync()
{
....
applicationModel.SummaryChangedEvent += OnNotify;
....
}
public async void OnNotify()
{
await InvokeAsync(() =>
{
StateHasChanged();
});
}
//Make sure to dispose the subscription
public void Dispose()
{
applicationModel.SummaryChangedEvent -= StateHasChanged;
}
}