如何在Autofac中具有较长使用寿命的对象中更改值?

时间:2019-02-19 08:33:38

标签: c# autofac

现有应用程序基于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”被更改。 我对此没有很好的解决方案。有人有经验吗?

1 个答案:

答案 0 :(得分:2)

您的代码段中有:

  • 名为ISerialPortController的{​​{1}}实现,已在应用程序中注册为单个实例。这意味着它将在Autofac容器的使用寿命(通常也是应用程序的使用寿命)中存活。
  • SerialPortController使用的值来自SerialPortController。该模型中的设置可能会在应用程序过程中发生更改,并且ISettingsModel进行此操作时需要开始使用新值。

我将首先回答一个简单的问题:无法在Autofac中重新初始化单例。单例的优点和缺点是……这是一个单例。构建完成后,就完成了。您必须删除整个容器并重新构建它,才能重新构建单例。

还有其他方法可以解决该问题,尽管这些方法实际上不需要重新初始化单例。

选项1:不要使控制器单例

将控制器设为SerialPortController,而不是使控制器成为单例。它消耗的设置仅在单个实例处于活动状态时才会保留。

您可能希望将其设为单例,例如创建起来很昂贵,或者充当资源池之类的东西。太酷了,还有更多选择。这只是最简单的答案。

选项2:将端口参数更改为更动态的

我的意思是,不是让InstancePerDependency使用文字端口号,而是使用函数来获取端口号。

例如,假设SerialPortController自动总是具有最新值。如果您向ISettingsModel求单身ISettingsModel,则它总是 。您可以更改控制器以改为使用ConveyorSerialPort

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也可以是单例) '会有一个captive dependency situation

但是,假设ISettingsModel每次解决都生成。为了获得新的设置,您必须获得一个新的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是一次性的。如果是一次性的(ISettingsModel),则Autofac会坚持使用直到容器被丢弃,从而导致内存泄漏。 There are ways to work around this, too.,但可能会变得有点复杂,我想为您提供一个有用的答案。该文档非常好(如果我自己也这么说的话),并且有很多示例。它很长,但是值得花时间检查一下。