【问题标题】:Inheriting from Owned<T>继承自拥有的<T>
【发布时间】:2016-10-24 17:58:02
【问题描述】:

我正在使用带有 Autofac 的 WebAPI 并开始一个长时间运行的任务(即开即忘的东西),该任务将在 HTTP 请求的生命周期后仍然存在。因此,我想防止ApiControllerApiController 生命周期结束后自动处理包含长时间运行任务的对象。

在 Web API 控制器中,我想使用 Owned&lt;T&gt; 类来注入其中一个依赖项,而不将其绑定到 ApiController 实例的 LifeTimeScope。似乎Owned&lt;T&gt; 是一个不错的选择,但我想从它继承,以便拥有可以使用 Moq 库模拟的虚拟(多态)Value 属性。

但是,当我从 Owned&lt;T&gt; 继承时,autofac 无法识别(由于反射?)我的 MyOwned&lt;T&gt; 并在下面抛出异常。

在“autofak.Meta”类型上使用“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的任何构造函数都不能使用可用的服务和参数调用:无法解析参数“System.Func”2[System.Int32 ,autofak.MyOwned'1[autofak.Root]] root' 的构造函数'Void .ctor(System.Func'2[System.Int32,autofak.MyOwned'1[autofak.Root]])'。

这是我的顶级类,它依赖于 Root 类。

class Meta
{
    public MyOwned<Root> Root { get; private set; }

    public Meta(Func<int, MyOwned<Root>> root)
    {
        Root = root(2);
    }
}

我的注册码如下:

var container = new ContainerBuilder();

container.RegisterType<child>();
container.RegisterType<grandchild>();
container.RegisterType<Root>();
container.RegisterType<Meta>();

var builder = container.Build();

是否可以从 Owned 继承并使其工作,还是我应该尝试不同的方法?

更新:

除了公认的解决方案之外,我还通过创建SingleInstance() 工厂以从根/应用程序生命周期范围创建新的LifeTimeScope 对象来遵循不同的路径。与Owned&lt;T&gt; 类类似,我创建了一个新类,它还为每个任务存储这个新生命周期(从根生命周期范围创建),并可以像在Owned&lt;T&gt; 中一样调用Dispose()

【问题讨论】:

  • 我的猜测是,您需要使用类似于配置 Owned&lt;T&gt; 的容器注册您的 MyOwned&lt;T&gt; 类。
  • 我认为Owned&lt;T&gt; 除了注册类型之外,我们不需要特殊注册,对吗?
  • 是的,它是为Owned&lt;T&gt; 内置的,但你的不是。找到Owned&lt;T&gt; 在 Autofac 的源代码中注册的位置应该不会太复杂,并且基本上为您的课程复制它。
  • 它使用IRegistrationSource注册here
  • 你的意思是把这段代码复制到我的项目中?

标签: c# autofac


【解决方案1】:

做你想做的最简单的方法是创建一个使用Owned&lt;T&gt;而不是从Owned&lt;T&gt;继承的新组件

public interface IOwned<T> : IDisposable
{
    T Value { get; }
}

public class MyOwned<T> : IOwned<T>
{
    public MyOwned(Owned<T> owned)
    {
        this._owned = owned;
    }

    private readonly Owned<T> _owned;

    public virtual T Value
    {
        get
        {
            return this._owned.Value;
        }
    }

    public void Dispose()
    {
        this._owned.Dispose();
    }
}

然后使用RegisterGeneric 方法和ExternallyOwned 注册您的组件。

builder.RegisterGeneric(typeof(MyOwned<>))
        .As(typeof(IOwned<>))
        .ExternallyOwned();

您需要将其声明为ExternallyOwned,因为没有此Autofac 将尝试在其ILifetimeScope 的末尾处理此组件,而Owned&lt;T&gt; 的目标是让您决定何时你处置组件。

另一种选择是创建自己的Owned&lt;T&gt; 组件,这要复杂得多,因为您需要实现IRegistrationSource 来管理由Owned&lt;T&gt; 组件创建的子ILifetimeScope

【讨论】:

  • @Cryil Durand:这是一个不错的解决方案。另外,我尝试了一些不同的东西。我创建了一个新的接口/对象,例如 IOwned/MyOwned,但没有从 Owned 继承,而是复制了它的实现。我的主要目标是创建一个独立于 WebAPI 中 HTTP 请求的生命周期。所以我创建了一个工厂对象(使用SingleInstance() 从根创建嵌套生命周期)我想注入并将它传递给控制器​​。然后我在我的自定义Owned&lt;T&gt; 类上手动调用Dispose()。我喜欢你的解决方案,谢谢。
  • @Deniz 您能否更新您的问题以包含您的更改?
猜你喜欢
  • 2010-10-22
  • 1970-01-01
  • 2011-12-16
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
相关资源
最近更新 更多