Question

Solution structure (Partial)

This is how the solution partially looks like.

Since I am using the Onion Architecture in a Winforms environment, hence I have the UI, Infrastructure and Core layers. All the layers are loosely coupled using Dependency Injection. What I want to achieve is that whenever a form from e.g. Accounts Forms (Class Library) is loaded, all the dependencies for that should be loaded in the UnityContainer i.e. types registered. These dependencies are interfaces and implementations present in Core and Infrastructure projects.

My confusion is that where should I write the code to register dependencies? What would be the Composition Root for this application? Please note that forms from e.g. Accounts Forms, HR Forms, etc are all loaded using reflection in the Main Windows application which references only the Base Forms Project.

After Eben Roux's suggestions

Here is how I am executing the wireup code when the assembly is loaded:

 Dim assemb As System.Reflection.Assembly    
              ...
              ... 
 If assemb IsNot Nothing Then
     Dim type As Type = GetType(IDependencyWiring)
     Dim modules As List(Of Type) = assemb.GetTypes().Where(Function(p) type.IsAssignableFrom(p) AndAlso p.IsClass).ToList()

     For Each [module] As Type In modules
         Dim argTypes As Type() = New Type() {}
         Dim cInfo As ConstructorInfo = [module].GetConstructor(argTypes)
         Dim dependencyWiringModule As IDependencyWiring = DirectCast(cInfo.Invoke(Nothing), IDependencyWiring)
         dependencyWiringModule.WireUp()
     Next
 End If

Here's is the Module having the WireUp method:

Public Class AccountModule : Implements IDependencyWiring

    Private Shared Container As IUnityContainer

    Public Sub New()
        Container = New UnityContainer()
    End Sub

    Public Sub WireUp() Implements IDependencyWiring.WireUp
        Container.RegisterType(Of IInterface1, Class1)()
        Container.RegisterType(Of IInterface2, Class2)()
        Container.RegisterType(Of IInterface3, Class3)()
        Container.RegisterType(Of IInterface4, Class4)()
    End Sub

    Public Shared Function Resolve(typeToResolve As Type) As Object
        Return Container.Resolve(typeToResolve.GetType())()
    End Function
End Class

So my questions now are:

  1. Is it the right approach to store the Container as Shared and use it to resolve dependencies via Resolve method?
  2. There is a problem in the way I am encapsulating the Resolve behavior of the Container. What would be the right syntax for that? I don't want to reference Unity on each of the form to be able to call the Resolve method, so I am encapsulating that i my own Resolve method. In this way I could easily replace the AccountModule with another one if I want to change the IOC Container without having the change the container references everywhere.
Was it helpful?

Solution

With this type of plug-in architecture you effectively end up with more than one composition root (of sorts). There will in all probability be some dependencies only your plug-in knows about and can wire up.

So part of your architecture should be the loading of the plug-ins. This probably happens somewhere in the main application in the wire-up bit (composition root) which would then give each plug-in the opportunity to perform its wiring.

Since not all plug-ins may need wiring one could make that explicit by using a seperate interface:

public interface IDependencyWiring
{
    public void WireUp(IDependencyContainer container); // <-- changed to conform to update
}

And then in the main composition root:

foreach (var plugin in plugins)
{
    var wiring = plugin as IDependencyWiring;

    if (wiring != null)
    {
        wiring.WireUp(myContainer);
    }
}

I hope that makes sense.

Update:

Firstly I would use a safe cast. TryCast in the VB.NET world. You could use dependency iversion to get rid of Unity from the actual plug-ins by using your own interface. Something like so:

public interface IDependencyContainer
{
    void Register(Type type);
    void Register<T>();
    void Resolve(Type type);
    void Resolve<T>();
}

Well, you would add what you need. Then pass in the reference to the container in the wire-up as I did up top public void WireUp(IContainer container);.

The Resolve behahiour is somewhat problematic in that you seem to be headed in a Service Locator direction. Try to get as much of the resolving done by the container by using constructor (or other) injection. Of course this works fine for Singleton components. For the Transient ones I'd rather use a Singleton factory that receives an instance of the IDependencyContainer (so that will also be registered), and it does the resolving (creation, really) for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top