Autofac 和 Func 工厂
Posted
技术标签:
【中文标题】Autofac 和 Func 工厂【英文标题】:Autofac and Func factories 【发布时间】:2014-01-02 05:10:37 【问题描述】:我正在使用 Caliburn.Micro 和 Autofac 开发一个应用程序。
在我的作文根目录中,我现在遇到了 Autofac 的问题: 我必须将全局使用的 IEventAggregator 注入到我的 FirstViewModel 中,以及必须仅由该 FirstViewModel 及其子级使用的第二个 IEventAggregator。
我的想法是让第二个注入为Owned<IEA>
,它可以工作,容器提供了一个不同的 IEA 实例。
public FirstViewModel(
IEventAggregator globalEA,
IEventAggregator localEA,
Func<IEventAggregator, SecondViewModel> secVMFactory)
当我必须向 SecondViewModel 提供事件聚合器时,问题就来了。
要创建 SecondViewModel,我使用工厂方法 Func<IEA, SecondVM>
。
SecondViewModel 的构造函数如下:
public SecondViewModel(IEventAggregator globalEA, IEventAggregator localEA)
我希望容器注入第一个作为注册的,第二个将是Func<IEA, SecVM>
的IEA参数。
这是我在容器中注册的函数:
builder.Register<Func<IEventAggregator, SecondViewModel>>(
c =>
(ea) =>
return new SecondViewModel(
c.Resolve<IEventAggregator>(),
ea);
);
但是当它被FirstViewModel
调用时,我收到以下错误:
Autofac.dll 中出现“System.ObjectDisposedException”类型的异常,但未在用户代码中处理
附加信息:此解析操作已经结束。使用 lambda 注册组件时,无法存储 lambda 的 IComponentContext 'c' 参数。相反,要么从 'c' 再次解析 IComponentContext,要么解析基于 Func 的工厂以从中创建后续组件。
我不明白问题出在哪里,请你帮帮我,我错过了什么?
谢谢。
【问题讨论】:
【参考方案1】:您在FirstViewModel
构造函数之外调用secVMFactory
,所以到那时ResolveOperation 已被释放,在您的工厂方法中c.Resolve
将抛出异常。
幸运的是,异常消息非常具有描述性,并告诉您该怎么做:
使用 lambda 注册组件时,IComponentContext 'c' 无法存储 lambda 的参数。相反,要么解决 IComponentContext 再次来自 'c'
因此,您需要从 c
解析 IComponentContext
并在您的工厂函数中使用它,而不是调用 c.Resolve
:
builder.Register<Func<IEventAggregator, SecondViewModel>>(c =>
var context = c.Resolve<IComponentContext>();
return ea =>
return new SecondViewModel(context.Resolve<IEventAggregator>(), ea);
;
);
【讨论】:
哈哈我试过这样做,但我把它放在内部函数中,所以我一直收到同样的错误! +1 还有一个问题:我应该在每次注册时都这样做以防止任何 vm 订单实例化重构吗? 这取决于您的要求,当您将Func
注册到容器中时,您始终可以c.Resolve<IComponentContext>();
,或者仅在您实际需要在您的容器中调用Resolve
的情况下才这样做工厂。
你可以在The Curious Case of a Deadlock in Autofac的帖子中阅读更多关于这个问题的信息
感谢您的出色回答,它解决了我的问题!我只是不完全理解解决方案。如果 c 在我们使用注册的 Func 时超出了范围,那么 context 怎么没有超出范围呢?谢谢!以上是关于Autofac 和 Func 工厂的主要内容,如果未能解决你的问题,请参考以下文章
[Asp.Net Core]Autofac整合.NET5 MVC