0

我有一个 dotnet 核心应用程序。我Startup.cs在 Autofac 中的寄存器类型/实现。我的一个注册需要事先访问服务。

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 容器尚未构建)。

我正在阅读有关在构建 autofac 容器后注册回调以执行某些内容的信息。所以我可以做这样的事情:

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?
});

但问题是,在我想使用该服务之后,不要执行启动服务或类似操作,而是继续注册需要我现在能够提供的设置的东西。

我可以简单地builder.Build()在回调结束时再次调用,以便简单地重建容器而没有任何问题吗?这似乎有点奇怪,因为构建器已经构建(这就是执行回调的原因)。

用autofac处理这种困境的最佳方法是什么?

更新 1:我读到像 builder.Update() 这样的东西现在已经过时了,因为容器应该是不可变的。这证实了我的怀疑,即构建容器、添加更多注册并再次构建不是一个好习惯。

换句话说,我可以理解,不应该使用注册构建回调来注册额外的东西。但是,问题仍然存在:如何处理这些问题?

4

1 回答 1

1

这个讨论问题解释了很多,包括解决必须更新容器的方法。我将在这里进行总结,但是该问题中有很多信息,尝试和复制所有信息都没有意义。

  • 熟悉注册组件和传递参数的所有方式。不要忘记解析参数、可以动态放置参数的模块等等。
  • Lambda 注册几乎解决了我们见过的所有这些问题。如果您需要注册一些提供配置的东西,然后稍后将该配置用作不同注册的一部分 - lambdas 将是巨大的。
  • 考虑中间接口,例如创建一个IUsernameProviderISettingsReader<string>. 可能是IUsernameProviderlambda(解决一些设置,读取特定设置等),然后下游组件可以IUsernameProvider直接使用。

这类问题很难回答,因为如果您利用 lambda 和参数之类的东西,有很多方法可以解决必须构建/重建/重新构建容器的问题——没有“最佳实践”,因为它总是取决于根据您的应用程序和您的需求。

就我个人而言,我通常会从 lambda 方法开始。

于 2018-11-02T15:52:58.093 回答