Mar 13, 2008 at 8:25 PM
Edited Mar 14, 2008 at 8:26 AM
I have a general idea of how object builder works, I've been using CAB for awhile and can work with it ok. I like the idea of Unity because it's just a IOC framework and doesn't require CAB or any other supporting framework. I had a few outstanding questions
though to enhance my understanding.
I start by configuring my container with a list of types that I want to store in the container.
Next my app fires up and I want to get some of the objects from the container to use.
So I can easy say: object myObject = UnityContainer.resolve<myType>();
Which gets me an instance of my type as long as the type was registered.
As this point I get a little confused. Do I now need to turn around and register this instance with the container? or is the instance registered because builder created it.
Also in the case of manual object creation... if I say:
object myObject = new myType();
myObject = UnityContainer.BuildUp(typeof(myType), myObject, null);
Now, instead of using the factory, I'm just creating my own type with new, then building it up with builder to fill in dependecies, etc... Does this register the instance? or like above do I have to now manually register the instance?
Also, a question about best practices.... So far I've configured my container to contain only "Singleton" objects and I'm letting the container manage the lifetime of these objects. I would also like to use my container as a repository for "on the fly" types
that I create somewhere in my app and register the instance with my container. For these instances that aren't
singleton, should I always register the instance with a key? ie "Name property"
Should I use a different container for these objects in the first place?
If I have 2 seperate containers in my configuration does builder cross containers to do dependency resolution?
Mar 15, 2008 at 6:22 AM
Edited Mar 15, 2008 at 6:23 AM
Let's see if I can help clear some of the confusion. No promises that I succeed, though. ;-)
When you say "container.RegisterType", you're telling the container "When you create an instance of this type, do this..." This lets you do type mapping (request an interface, get a concrete instance), and lets you specify the lifetime (defaults to "create
a new one every time" unless you specify otherwise."
When you say "container.RegisterInstance", you're telling the container "When somebody asks for this type, hand them this, and here's how you hold onto this instance I'm giving you." So the container doesn't create any objects, and it holds on to it according
to the lifetime you give it (defaults to per-container singleton; the instance sticks around as long as the container does).
So it sounds like you want all your created objects to be singletons - create them once, return the same instance every time. To do this, when you register the type, include a ContainerControlledLifetimeManager:
container.RegisterType<IFoo, Foo>(new ContainerControlledLifetimeManager());
This will make the container hold onto the instances every time. This also answers your later question about "On the fly" objects. These have what we call a transient lifetime - the container will create a new instance every time. All you need to do is not
specify a lifetime manager when you register the type, and the container will do exactly what you asked.
With manual object creation, that feature was primarily intended for cases where some other framework is creating the objects for you (ASP.NET pages, web services, WPF objects created via XAML). As a result, the lifetime is ignored for these types. If you really
want to get back the built-up object from the container, you would have to manually register the instance in that case, but I'd really ask yourself why you're doing that before going down that road.
You choose whether to register with a key or not if you have the same type that needs to be resolved with different dependencies fulfilled. It doesn't really matter if it's a singleton or not.
Should you use a different container? You probably don't need to. Hierarchical containers are most useful to manage scope, but you could use them for keeping separate sets of configurations if you want.
There is nothing automatic about the configuration. The "builder" will not cross containers to build anything. You must explicitly apply a named configuration to a container to have its settings be used. In fact, you could do:
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
IUnityContainer container = new UnityContainer();
That code applies two sets of configuration settings to the same container. Last one in wins.
Hope this helps,