Search code examples
c#unity-container

How do you use RegisterFactory?


I am having problems understanding how to use RegisterFactory. The code below works fine with the older InjectionFactory but I am having problems when I try to do the same thing with RegisterFactory.

In the sample code there is an uncommented section that uses RegisterFactory and a commented section that uses InjectionFactory. The InjectionFactory code works fine but the RegisterFactory throws a ResolutionFailedException.

Unity.ResolutionFailedException: 'The current type, ConsoleApp1.IFoo, is an interface and cannot be constructed. Are you missing a type mapping?'

What am I doing incorrectly?

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

        container.RegisterType<IFoo, Foo1>("Foo1");
        container.RegisterType<IFoo, Foo2>("Foo2");

        container.RegisterType<MainViewModel>();

        // This does not work
        container.RegisterFactory<Func<string, IFoo>>((c, type, name) => c.Resolve<IFoo>(name));

        // This works
        //container.RegisterType<Func<string, IFoo>>(new InjectionFactory(
        //    ctx => new Func<string, IFoo>(name => container.Resolve<IFoo>(name))));


        var vm = container.Resolve<MainViewModel>();
    }
}

public class MainViewModel
{
    public MainViewModel(Func<string, IFoo> fooFactory)
    {
        var foo1 = fooFactory.Invoke("Foo1");
        var foo2 = fooFactory.Invoke("Foo2");
    }
}

public interface IFoo
{
    string Name { get; }
}

public class Foo1 : IFoo
{
    public string Name { get; set; }

    public Foo1()
    {
        Name = "Foo1";
    }
}

public class Foo2 : IFoo
{
    public string Name { get; set; }

    public Foo2()
    {
        Name = "Foo2";
    }
}

Solution

  • If you're registering with RegisterFactory, you tell Unity how to construct the instance. But Unity already knows how to construct Foo1 and Foo2, because you registered those already.

    What you want is a factory for you to use, that's what RegisterType does, so this works.

    Normally, such a factory would implement some IFooFactory, thus making the context more obvious. But as long as Func<string, IFoo> is registered only used once, it works fine, too, of course.