how to call a "factory method" instead a constructor

Apr 16, 2008 at 12:36 PM
Hello everyone,

I am totally lost in this new "thing" called Unity. I now the DI concept, but I do not know if I am fool or if the documentation is quite weak.

Well, let´s go with my problem:
I want to achieve the following, some of my classes are created in a CreateInstance() method, like a singleton but always creating the object. I am using this trying to force everybody to use the policyinjection. With this I can have my constructors private. But now I want to use Unity inside of that methods to create another objects which are constructed in the same way, calling CreateInstance().

The code should be something like this, from a business class I want to create the DAO:

user business class
public static IUserBusiness CreateInstance()
{

//some unity staff, which later should go to configuration.
IUserDAO userDao = container.Resolve<IUserDAO >(); <-- Here it should call createinstance from the UserDAO class.

IUserBusiness negocioUsuario = new UserBusiness(userDao );

return BaseFactory<IUserBusiness , IUserBusiness >.Wrap(userBusiness); //this call policy injection.
}


So, how can I call CreateInstance from unity?

Thanks in advance.
Apr 16, 2008 at 8:10 PM
I think if your CreateInstance is static, Unity can't call it (it doesn't even give any exception).
Apr 17, 2008 at 4:25 AM
Edited Apr 17, 2008 at 4:27 AM
The Unity source comes with an example extension, StaticFactory. This can be used to specify a delegate to call to resolve the object instead of using the standard policies.

The downside of this is that you take over ALL injection, so you'll need to also resolve any properties manually inside your delegate.

Usage looks like this (using C# 3.0 lambda expressions):

container.AddNewExtension<StaticFactory>();
container.Configure<IStaticFactoryConfiguration>()
    .RegisterFactory<IUserDAO>( container => UserDAO.CreateInstance() );

Now, when you Resolve<IUserDAO>(), it'll invoke the delegate and call your CreateInstance method.

-Chris
Apr 17, 2008 at 7:56 AM
Edited Apr 17, 2008 at 8:00 AM

container.AddNewExtension<StaticFactory>();
container.Configure<IStaticFactoryConfiguration>()
    .RegisterFactory<IUserDAO>( container => UserDAO.CreateInstance() );

¡Works perfect! Now I will try to put this into configuration, I have problems I will ask.

¡Thanks so much!
Apr 17, 2008 at 8:17 AM
Ouch, I am quite sleepy today.

I think it is imposible to configure it in a config. Am I right? Any alternative?
Apr 17, 2008 at 5:43 PM
No, you can't put source code into configuration.
Apr 18, 2008 at 12:03 PM

ctavares wrote:
No, you can't put source code into configuration.


But i could put a factory of containers in a assembly and use it through configuration. If I want a mock i should put another factory with the mocks.

Any performance issue with that?
Oct 19, 2010 at 3:13 PM
I might need some help with this:
My singleton class:
 
    private readonly IContainer container;

    private TriggerPool(IContainer container)
    {
      if (container == null)
      {
        throw new ArgumentNullException("container", "IContainer cannot be null");
      }

      this.container = container;
    }

    public static TriggerPool Instance
    {
      get
      {
        // Only create a new instance if one doesn't already exist.
        if (instance == null)
        {
          // Use this lock to ensure that only one thread is access this block of code at once.
          lock (syncRoot)
          {
            if (instance == null)
            {
              instance = new TriggerPool();
            }
          }
        }

        // Return instance where it was just created or already existed.
        return instance;
      }
    }

and configuring the container:

      container.RegisterInstance<IContainer>(container);
      container.AddNewExtension<StaticFactoryExtension>().Configure<IStaticFactoryConfiguration>().RegisterFactory<TriggerPool>(c => TriggerPool.Instance);
      container.Resolve<TriggerPool>();
Now how do I make the Instance property create the class, injected with the container?
Oct 20, 2010 at 1:25 AM

You can't really, unless the container is a global that you've guaranteed is set up ahead of time before the Instance property is ever called. But more importantly - why would you want to do this at all? Why not just resolve TriggerPool directly, setting it to ContainerControlled and let the container manage the lifetime?

Why not just do:

container.RegisterType<TriggerPool>(new ContainerControlledLifetimeManager());

container.Resolve<TriggerPool>();

It's the same effect, it's a lot simpler, and you don't need to implement any singleton pattern in the TriggerPool class itself, the container handles that part for you. Oh, and you can actually do it.

 

 

Oct 20, 2010 at 8:46 AM

gracias, this might just be what I need, I'll try it out