在Autofac中注册回调并在回调中再次构建容器 [英] Register callback in Autofac and build container again in the callback
问题描述
我有一个dotnet核心应用程序。
我的 Startup.cs
在Autofac中注册类型/实现。
我的一个注册需要先前访问服务。
I have a dotnet core application.
My Startup.cs
registers types/implementations in Autofac.
One of my registrations needs previous access to a service.
var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterSettingsReaders(); // this makes available a ISettingsReader<string> that I can use to read my appsettings.json
containerBuilder.RegisterMyInfrastructureService(options =>
{
options.Username = "foo" //this should come from appsettings
});
containerBuilder.Populate(services);
var applicationContainer = containerBuilder.Build();
难题是,当我不得不 .RegisterMyInfrastructureService
我需要提供刚刚注册过的 ISettingsReader< string>
(尚未构建Autofac容器)。
The dilemma is, by the time I have to .RegisterMyInfrastructureService
I need to have available the ISettingsReader<string>
that was registered just before (Autofac container hasn't been built yet).
我正在阅读有关在构造autofac容器后向回调注册以执行某些操作的信息。所以我可以做这样的事情:
I was reading about registering with callback to execute something after the autofac container has been built. So I could do something like this:
builder.RegisterBuildCallback(c =>
{
var stringReader = c.Resolve<ISettingsReader<string>>();
var usernameValue = stringReader.GetValue("Username");
//now I have my username "foo", but I want to continue registering things! Like the following:
containerBuilder.RegisterMyInfrastructureService(options =>
{
options.Username = usernameValue
});
//now what? again build?
});
但问题是,在我要使用该服务后,不要做启动服务或类似于,但要继续注册需要我现在能够提供的设置的。
but the problem is that after I want to use the service not to do something like starting a service or similar but to continue registering things that required the settings I am now able to provide.
我可以简单地再次致电在回调的末尾显示builder.Build()
,以便仅重建容器而不会出现任何问题?这似乎有点奇怪,因为已经构建了构建器(这就是执行回调的原因)。
Can I simply call again builder.Build()
at the end of my callback so that the container is simply rebuilt without any issue? This seems a bit strange because the builder was already built (that's why the callback was executed).
用autofac处理这一难题的最佳方法是什么?
What's the best way to deal with this dilemma with autofac?
更新1:我读到诸如builder.Update()之类的东西现在已经过时了,因为容器应该是不可变的。这证实了我的怀疑,即建立容器,添加更多注册并再次构建不是一个好习惯。
UPDATE 1: I read that things like builder.Update() are now obsolete because containers should be immutable. Which confirms my suspicion that building a container, adding more registrations and building again is not a good practice.
换句话说,我可以理解,使用寄存器构建回调应该不用于注册其他内容。但是,问题仍然存在:如何处理这些问题?
In other words, I can understand that using a register build callback should not be used to register additional things. But then, the question remain: how to deal with these issues?
推荐答案
此讨论问题解释了很多内容,包括解决必须更新容器的方法。我将在这里进行总结,但是在该问题中有大量信息无法尝试全部复制。
This discussion issue explains a lot including ways to work around having to update the container. I'll summarize here, but there is a lot of information in that issue that doesn't make sense to try and replicate all over.
- 熟悉所有注册组件的方式并传递参数。不要忘记诸如解析参数,可以动态放置参数的模块之类的东西。
- Lambda注册几乎解决了我们所遇到的所有问题。如果您需要注册提供配置的内容,然后稍后将该配置用作其他注册的一部分,则lambda将会非常庞大。
- 考虑中间接口,例如创建<$ c $由
ISettingsReader< string>
支持的c> IUsernameProvider 。IUsernameProvider
可以是lambda(解析某些设置,读取特定设置等),然后下游组件可以使用IUsernameProvider $
- Be familiar with all the ways you can register components and pass parameters. Don't forget about things like resolved parameters, modules that can dynamically put parameters in place, and so on.
- Lambda registrations solve almost every one of these issues we've seen. If you need to register something that provides configuration and then, later, use that configuration as part of a different registration - lambdas will be huge.
- Consider intermediate interfaces like creating an
IUsernameProvider
that is backed byISettingsReader<string>
. TheIUsernameProvider
could be the lambda (resolve some settings, read a particular one, etc.) and then the downstream components could take anIUsernameProvider
directly.
这类问题很难回答,因为其中有 个利用lambda和参数之类的方法来构建/重建/重新构建容器的方法-没有最佳实践,因为它始终取决于您的应用和您的需求。
These sorts of questions are hard to answer because there are a lot of ways to work around having to build/rebuild/re-rebuild the container if you take advantage of things like lambdas and parameters - there's no "best practice" because it always depends on your app and your needs.
我个人而言,我通常会从lambda方法开始。
Me, personally, I will usually start with the lambda approach.
这篇关于在Autofac中注册回调并在回调中再次构建容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!