configure Unity to resolve a constructor parameter and interface

1

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

c#
.net
inversion-of-control
unity-container
asked on Stack Overflow Mar 29, 2018 by John Livermore • edited Apr 8, 2020 by d219

2 Answers

3
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>();
answered on Stack Overflow Mar 29, 2018 by Always Learning • edited Mar 29, 2018 by Always Learning
1

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).

answered on Stack Overflow Mar 29, 2018 by NightOwl888 • edited Mar 29, 2018 by NightOwl888

User contributions licensed under CC BY-SA 3.0