c# - 如何更改 Autofac 中具有较长生命周期的对象中的值?

标签 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”已更改。 我没有看到一个好的解决方案。有人有这方面的经验吗?

最佳答案

从您的代码片段中,您可以:

  • 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/

相关文章:

C# 可执行属性

c# - 引用程序集中的条件编译

c# - 比赛 : Storing an arbitrary number of fields

c# - ResolutionException - 获取 "Required dependency of type *********** could not be resolved"

dependency-injection - C# 中的 autofac "Hello World"应用程序 - 初始化

.net-core - .NET Core 默认依赖注入(inject)与 CaSTLe DynamicProxy

c# - 为什么我的 NHibernate 更新不工作?

javascript - 如何在 JavaScript 中访问嵌入式 ASP.NET GlobalResources?

c# - Visual Studio 2010 项目转换为 Visual Studio 2012

autofac - 使用 Autofac 在特定命名空间中注入(inject)依赖项