Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I combine a Controlled Lifetime relationship type (i.e. Owned<T>) with a delegate factory?

Tags:

autofac

In my application, I have a service that requires a constructor parameter not resolved by Autofac, that I instantiate using a delegate factory:

public class Service
{
    public Service(string parameter /*, ... other dependencies */)
    {
    }

    public delegate Service Factory(string parameter);
}

This works great! I really love this feature.

I also like the Controlled Lifetime relationship, so I can let my component depend on a Func<Owned<ISomething>> like this:

public class Component
{
    private Func<Owned<ISomething>> _somethingFactory;

    /* constructor omitted for brevity */

    public void DoSomethingUseful()
    {
       using (var ownedSomething = _somethingFactory())
       {
           /* Lots of useful code here */
       }
    }
}

My problem is that now I want to combine the two. I can't have an instance of Func<Owned<Service>> injected, because it needs that parameter, so my current solution is to abstract the factory away into another service, say IServiceFactory:

public interface IServiceFactory
{
    Service Create(string parameter);
}

...implemented as such:

public class ServiceFactory : IServiceFactory
{
    private Service.Factory _internalFactory;

    public ServiceFactory(Service.Factory internalFactory)
    {
        _internalFactory = internalFactory;
    }

    public Service Create(string parameter)
    {
        return _internalFactory(parameter);
    }
}

My component then becomes this:

public class Component
{
    Func<Owned<IServiceFactory>> _serviceFactoryFactory;

    /* ... */ 
}

The need for such a field name leaves a bad taste in my mouth to the point that I suspect there must be a cleaner way to handle this case.

Is there another way?

like image 972
Dave Van den Eynde Avatar asked Dec 03 '25 01:12

Dave Van den Eynde


1 Answers

You could change your injected factory to include the string parameter:

private Func<string, Owned<ISomething>> _somethingFactory;

Then you can pass the string to the factory when you want to create a new instance:

public void DoSomethingUseful()
{
   using (var ownedSomething = _somethingFactory("my parameter"))
   {
       /* Lots of useful code here */
   }
}

I've created a .NET Fiddle with a small working sample.

like image 171
fknx Avatar answered Dec 05 '25 19:12

fknx