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:
- Is it the right approach to store the Container as Shared and use it to resolve dependencies via Resolve method?
- 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.
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:
And then in the main composition root:
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: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 theIDependencyContainer
(so that will also be registered), and it does the resolving (creation, really) for you.