Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

configure Unity to resolve a constructor parameter and interface

I have a FaxService class that takes two constructor parameters.

public FaxService(string phone, IFaxProvider faxProvider)

How is Unity configured to send a string for the first parameter and an IFaxProvider instance for the second? I realize I can inject another service that provides the string, but I am looking for a solution where I don't have to change the FaxService constructor parameters.

This is what I have so far...

class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();

        var phone = "214-123-4567";
        container.RegisterType<IFaxProvider, EFaxProvider>();
        container.RegisterType<IFaxService, FaxService>(phone);

        var fax = container.Resolve<IFaxService>();
    }
}

public interface IFaxService { }

public interface IFaxProvider { }

public class FaxService : IFaxService
{
    public FaxService(string phone, IFaxProvider faxProvider) { }
}

public class EFaxProvider : IFaxProvider { }

but it throws...

Unity.Exceptions.ResolutionFailedException HResult=0x80131500
Message=Resolution of the dependency failed, type = 'ConsoleApp3.IFaxService', name = '(none)'. Exception occurred while: while resolving.

enter image description here

like image 253
John Livermore Avatar asked Jun 17 '26 18:06

John Livermore


2 Answers

var container = new UnityContainer();
var phone = "214-123-4567";
container.RegisterType<IFaxProvider, EFaxProvider>();
container.RegisterType<IFaxService, FaxService>(new InjectionConstructor(phone, typeof(IFaxProvider)));

var fax = container.Resolve<IFaxService>();
like image 141
Always Learning Avatar answered Jun 19 '26 07:06

Always Learning


I am looking for a solution where I don't have to change the FaxService constructor parameters.

There is nothing built into Unity to do this without specifying at least the types of all constructor parameters.

var container = new UnityContainer();
var phone = "214-123-4567";
container.RegisterType<IFaxService, FaxService>(new InjectionConstructor(phone, typeof(IFaxProvider)));
container.RegisterType<IFaxProvider, EFaxProvider>();

var fax = container.Resolve<IFaxService>();

The list of parameters would need to change every time the constructor changes.

Workaround

If you don't want to change your DI registration if the constructor changes for FaxService, build an abstract factory to separate the string/primitive parameters from the services. Pass services through the constructor parameters of the factory. Pass string and primitive parameter types through the Build method parameters.

public class FaxServiceFactory
{
    private readonly IFaxProvider faxProvider;
    public FaxServiceFactory(IFaxProvider faxProvider)
    {
        this.faxProvider = faxProvider ?? throw new ArgumentNullException(nameof(faxProvider));
    }

    public IFaxService Create(string phone)
    {
        return new FaxService(phone, this.faxProvider);
    }
}

And then register like:

var container = new UnityContainer();

var phone = "214-123-4567";
container.RegisterType<FaxServiceFactory>();
container.RegisterType<IFaxProvider, EFaxProvider>();
container.RegisterInstance<IFaxService>(container.Resolve<FaxServiceFactory>().Create(phone));

var fax = container.Resolve<IFaxService>();

Another possibility is to use a DI container that allows you to specify partial lists of constructor parameters (Autofac, Ninject, StructureMap, and Castle Windsor all do this out of the box).

like image 41
NightOwl888 Avatar answered Jun 19 '26 08:06

NightOwl888



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!