Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity auto-factory with params

I'm trying to figure out the correct way to inject an auto-factory which takes params, or even if this is possible with Unity.

For example I know I can do this:

public class TestLog
{
     private Func<ILog> logFactory;

     public TestLog(Func<ILog> logFactory)
     {
          this.logFactory = logFactory;
     }
     public ILog CreateLog()
     {
         return logFactory();
     }
}

Container.RegisterType<ILog, Log>();
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog();

Now what I'll like to be able to do is:

public class TestLog
{
     private Func<string, ILog> logFactory;

     public TestLog(Func<string, ILog> logFactory)
     {
          this.logFactory = logFactory;
     }
     public ILog CreateLog(string name)
     {
         return logFactory(name);
     }
}

Container.RegisterType<ILog, Log>();
TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog("Test Name");

Unfortunately this doesn't work. I can see how you can set up custom factories for creating instances in Unity, just can't seem to fund any clear examples for this example.

Obviously I could create my own factory but I'm looking for an elegant way to do this in Unity and with minimum code.

like image 677
TheCodeKing Avatar asked Sep 29 '10 19:09

TheCodeKing


2 Answers

Sorry to be one of those annoying people who answer their own questions but I figured it out.

public class TestLog
{
    private Func<string, ILog> logFactory;

    public TestLog(Func<string, ILog> logFactory)
    {
         this.logFactory = logFactory;
    }
    public ILog CreateLog(string name)
    {
        return logFactory(name);
    }
}

Container.RegisterType<Func<string, ILog>>(
     new InjectionFactory(c => 
        new Func<string, ILog>(name => new Log(name))
     ));

TestLog test = Container.Resolve<TestLog>();
ILog log = test.CreateLog("Test Name");
like image 170
TheCodeKing Avatar answered Oct 21 '22 04:10

TheCodeKing


The answer by @TheCodeKing works fine, but in most (possibly all?) cases could be shortened to the following:

Container.RegisterInstance<Func<string, ILog>>(name => new Log(name));

(note that I'm using RegisterInstance() instead of RegisterType())

Since the Func<> implementation is already a kind of factory there's usually no need to wrap it in a InjectionFactory. It only ensures that each resolution of the Func<string, ILog> is a new instance, and I can't really think of a scenario that requires this.

like image 30
TheBigB Avatar answered Oct 21 '22 03:10

TheBigB