现有应用程序基于 MVVM Light 并使用 autofac 容器来创建对象。在应用程序的生命周期中,需要使用新参数重建已创建的对象。我对 autofac 缺乏经验
示例:
containerBuilder.RegisterType<SerialPortController>().Named<ISerialPortController>("ConveyorController").WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "portName",
(pi, ctx) => ctx.Resolve<ISettingsModel>().ConveyorSerialPort)).SingleInstance();
例如,“portName”已更改。 我没有看到一个好的解决方案。有人有这方面的经验吗?
最佳答案
从您的代码片段中,您可以:
- 安
ISerialPortController
实现称为SerialPortController
作为单个实例在应用程序中注册。这意味着它将与 Autofac 容器的生命周期一样存在,这通常也是应用程序的生命周期。 - 一个值,
SerialPortController
使用来自ISettingsModel
。该模型中的设置可能会在应用程序过程中以及执行SerialPortController
时发生变化。需要开始使用新值。
我将首先回答一个简单的问题:在 Autofac 中无法重新初始化单例。单例的优点和缺点是......它是单例。一旦建成,就建成了。您必须删除整个容器并重建它才能重建单例。
还有其他方法可以解决该问题,尽管这些方法实际上并不需要重新初始化单例。
选项 1:不要将 Controller 设置为单例
不要将 Controller 设置为单例,而是将其设置为 InstancePerDependency
。它消耗的设置仅在单个实例处于事件状态时才会保留。
您可能有一些原因希望它成为单例,例如创建它的成本很高,或者它可能充当资源池或其他东西。太好了,还有更多选择。这只是最简单的答案。
选项 2:将端口参数更改为更动态的参数
我的意思是,不要使用 SerialPortController
接受一个文字端口号,让它接受一个用于检索端口号的函数。
例如,假设 ISettingsModel
自动始终具有最新值。如果你问一个单例ISettingsModel
对于ConveyorSerialPort
它总是是最新的。您可以将 Controller 更改为 ISettingsModel
相反。
public class SerialPortController
{
private readonly ISettingsModel _model;
public SerialPortController(ISettingsModel model)
{
this._model = model;
}
public void DoSomething()
{
// port will always be up to date.
var port = this._model.ConveyorSerialPort;
this.CommunicateOn(port);
}
}
在本例中,取决于 ISettingsModel
保持其值新鲜,但只要发生这种情况, Controller 就可以是单例(理想情况下, ISettingsModel
也可以,否则您将拥有 captive dependency situation 。
但是我们可以说ISettingsModel
每次解决时都会生成。为了获得新的设置,您必须获得新的 ISettingsModel
。没关系,您也可以使用 Autofac 来做到这一点,使用 Func<T>
:
public class SerialPortController
{
private readonly Func<ISettingsModel> _modelFactory;
public SerialPortController(Func<ISettingsModel> modelFactory)
{
this._modelFactory = modelFactory;
}
public void DoSomething()
{
// port will always be up to date.
var port = this._modelFactory().ConveyorSerialPort;
this.CommunicateOn(port);
}
}
自动生成的Func<ISettingsModel>
将重新推出全新ISettingsModel
从容器中。由于您的 Controller 是单例,因此它将来自容器的根。 小心如果 ISettingsModel
是一次性的。如果它是一次性的 ( IDisposable
),则 Autofac 将保留它,直到容器被丢弃,从而导致内存泄漏。 There are ways to work around this, too.但这可能会变得有点复杂,我想给你一个有用的答案。该文档非常好(如果我自己这么说的话)并且有很多示例。虽然很长,但值得花时间查看。
关于c# - 如何更改 Autofac 中具有较长生命周期的对象中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54761843/