首页 > 解决方案 > 在 Autofac 中处理通过构造函数注入的没有生命周期范围的组件

问题描述

我不明白为什么我的组件永远不会在 Autofac 中处理/发布。我有一个标准的 WPF 应用程序,它从 app.xaml.cs 开始,解析MainVM这是一个单例并显示MainWindowwith DataContextof MainVM

然后我主要使用我的注册组件的构造函数注入,这些组件是单例或(默认)instancePerDependency,每次注入时都会创建新的。或者我有时有工厂来传递一些自定义参数。

例如,工厂看起来像这样:

public delegate MyComponent Factory(string parameter1, int parameter2);

注入看起来像这样:

public MainVM(MyComponent.Factory createMyComponent)
...
public void makeNewComponent()
{
  var myComponent = this.createMyComponent("test", 1);
  myComponent.DoStuff();
}

这就是我的组件的注册方式:

containerBuilder.RegisterType<T>().OnActivated(args => (args.Instance as IInitializable)?.Initialize());

builder.RegisterType<MyComponent>().As<IMyComponent>().OnActivated(args => (args.Instance as IInitializable)?.Initialize());

// This will never be called in my code: .OnRelease(instance => (instance as IInitializable)?.Uninitialize())*/;

现在让我们想象一下,我在其他视图模型中创建了许多这样的视图模型,所以我们喜欢MainVM-> MyComponent-> OtherComponent,并且在操作完成后,我希望它们处理(或只是以某种方式从内存中消失),调用Dispose()OnRelease从 Autofac调用事件。这些中的任何一个都可以。

但我的问题是 - 我没有使用这种模式:

using(var scope = container.BeginLifetimeScope())

因为我没有在从 { 到 } 的一种方法中工作。我需要我的组件以多种方法存在于对象中,并且在我ViewModel1从视图堆栈中删除之后,我希望在其中创建的所有内容都ViewModel1可以释放/释放其子级。是什么导致组件认为它们可以被丢弃?如果视图模型不是在生命周期范围内创建的,我如何告诉它不再需要它?

标签: c#.netwpfdependency-injectionautofac

解决方案


你不应该关心没有实现的类IDisposable。即使它们的实例是由 Autofac 容器创建的,一旦没有对它们的 GC 根引用(例如,视图已关闭并且对它的所有引用都被null-ed),对象将自动被 GC。这会影响整个依赖关系图——不管它有多深。

如果你设置中有IDisposable对象,容器当然会保存对它们的引用,因为它需要处理这些对象。但是,您仍然可以控制这种情况的发生方式。

您可以为此使用依赖项的Owned<T>实例。IDisposable

考虑你的例子:

class MainVM 
{
    private readonly Owned<IMyComponent> _myComponent;

    public MainVM(Owned<IMyComponent> myComponent) => _myComponent = myComponent;

    public void DoStuff() => _myComponent.Value.DoStuff();

    public void OnViewClosed() => _myComponent.Dispose();
}

class MyComponent : IMyComponent, IDisposable
{
    public MyComponent(IOtherComponent otherComponent) { /* ... */ }
}

class OtherComponent : IOtherComponent, IDisposable
{
}

现在,当OnViewClosed方法被调用时,拥有的实例MyComponent将被处理掉,包括所有MyComponent非共享的、一次性的依赖项——OtherComponent在我们的示例中。

考虑阅读文档中有关拥有的实例的信息。


推荐阅读