Deniz Deniz - 1 month ago 11
C# Question

Inheriting from Owned<T>

I am using WebAPI with Autofac and starting a long running task (fire and forget stuff) which will be alive after the lifetime of HTTP request. Therefore, I would like to prevent the

ApiController
to automatically dispose the object which consists the long running task, after
ApiController
lifetime ends.

In the Web API controller I would like to use
Owned<T>
class in order to inject one of the dependencies without binding it to the
LifeTimeScope
of the
ApiController
instance. It seems
Owned<T>
is a good choice for that, but I would like inherit from it in order to have virtual (polymorphic)
Value
property which I can mock with the Moq library.

However, when I inherit from
Owned<T>
autofac does not recognize (due to the reflection?) my
MyOwned<T>
and throws the exception below.


None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'autofak.Meta' can be invoked with the available services and parameters: Cannot resolve parameter 'System.Func'2[System.Int32,autofak.MyOwned'1[autofak.Root]] root' of constructor 'Void .ctor(System.Func'2[System.Int32,autofak.MyOwned'1[autofak.Root]])'.


This is my top-level class which depends on Root class.

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

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


My registration code is below:

var container = new ContainerBuilder();

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

var builder = container.Build();


Is it possible to inherit from Owned and make it work or should I try a different approach?

Update:

Besides the accepted solution, I also followed a different path by creating a
SingleInstance()
factory in order to create new
LifeTimeScope
objects from the root/application lifetimescope. Similar to
Owned<T>
class I created a new class which also stores this new lifetime (created from root lifetime scope) for each task and makes it possible to call
Dispose()
as in the
Owned<T>
.

Answer

The easiest way to do what you want would be to create a new component that uses a Owned<T> instead of inheriting from Owned<T>

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();
    }
}

Then register your component using the RegisterGeneric method and ExternallyOwned.

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

You need to declare it as ExternallyOwned because without this Autofac will try to dispose this component at the end of its ILifetimeScope and the goal of Owned<T> is to let you decide when you dispose the component.

Another option would be to create your own Owned<T> component which is a lot more complex because you will need to implement IRegistrationSource to manage the child ILifetimeScope created by the Owned<T> component.

Comments