Implementing Unity on a ERP like scenario...

Apr 23, 2008 at 9:46 PM
Hi,
I'm having some problems porting the examples to an ERP like scenario.

Lets say I have a Windows Forms application "APP1" and 3 more class library modules: Module1, Module2, Module3
I need to access those modules from APP1 but also need that the modules interact with each other without having explicit references (mostly because that would make bi-directional references that is not allowed).

My initial idea was to create a modal class library project that all projects would reference and where I would put all the "interop" interfaces.
Then, also on that modal project I wanted to declare the containers, one for each module, so that the modules could access each others containers and this way resolve each other objects... but I couldn't...
The registration process needs a reference to the actual object that needs to be returned and I can't reference a Module from the modal project because that would create a circular reference...

I know I'm thinking this in the wrong way, I just don't seem to quite understand where to put the Containers so they can be accessed from the other modules...


I use decoupled applications for quite some time now and in my implementations I use reflection to seek in the assemblies for implementations of public interface and the objects are returned as those interfaces, the caller never knows about the object itself and only have access to the interface implementation part of it.

Thanks,
Alex
Apr 24, 2008 at 10:32 PM
My first question is: why does each library have its own container?

In the kind of truly loosely coupled system, what I'd probably do is have APP1 create a single container, and then either register the classes from the modules in that one container, or dynamically load the modules, and have each one implement some kind of module initializer method that receives a container and registers and resolves things in it.

Kind of how CAB or WCSF does it, if your familiar with those packages.
Apr 25, 2008 at 3:27 AM
From what I see from the demos, to register an object we need to reference it explicitly and to do so I need to reference Module1 and Module2 also explicitly.
I don't have explicit relations between projects... but even if I do reference Module1&2 from APP1, and if I only have one container and it's inside APP1, how can I, from Module1, access the container that's inside APP1 from Module2?

Maybe I'm just stuck on my current way of doing this but I'm not quite getting how this works...

Do you have a demo project where I can see this working?

Thanks,
Alex
Apr 25, 2008 at 5:14 AM
The simplest version I have used is something like this
using System.Collections.Generic;
using System.Configuration;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
 
namespace CodePlex.Sample.Unity
{
    interface IModuleInitializer
    {
        void Initialize(IUnityContainer container);
    }
 
    public abstract class ModuleInitializer : IModuleInitializer
    {
        public virtual void Initialize(IUnityContainer container)
        {
        }
    }
 
    public static class Container
    {
        private static readonly object syncRoot = new object();
        private static IUnityContainer container;
 
        public static IUnityContainer Current
        {
            get
            {
                // use your favorite singleton pattern here
                if (container == null)
                {
                    lock (syncRoot)
                    {
                        if (container == null)
                            container = CreateContainer();
                    }
                }
                return container;
            }
        }
 
        private static IUnityContainer CreateContainer()
        {
            IUnityContainer container = new UnityContainer();
 
            UnityConfigurationSection config = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
            if (config == null) return container;
 
            if (config.Containers.Default == null) return container;
 
            config.Containers.Default.Configure(container);
 
            IEnumerable<IModuleInitializer> initializers = container.ResolveAll<IModuleInitializer>();
            foreach (IModuleInitializer initializer in initializers)
                initializer.Initialize(container);
 
            return container;
        }
    }
}

Your modules reference the CodePlex.Sample.Unity assembly and create a classes that inherit from CodePlex.Sample.Unity.ModuleInitializer In your config file, you add the standard <unity> config section and register each of your ModuleInitializer classes. Obviously, you can get fancier as the WCSF does and automatically finds these initializers, but I have kept it simple for now (until someone submits a contrib package).

To build up an object from somewhere in your code, you reference the CodePlex.Sample.Unity assembly and do something like
    public interface ISomething { }
 
    public class Foo
    {
        public Foo()
        {
            ISomething something = CodePlex.Sample.Unity.Container.Current.Resolve<ISomething>();
        }
    }


AlexCode wrote:
From what I see from the demos, to register an object we need to reference it explicitly and to do so I need to reference Module1 and Module2 also explicitly.
I don't have explicit relations between projects... but even if I do reference Module1&2 from APP1, and if I only have one container and it's inside APP1, how can I, from Module1, access the container that's inside APP1 from Module2?

Maybe I'm just stuck on my current way of doing this but I'm not quite getting how this works...

Do you have a demo project where I can see this working?

Thanks,
Alex