OK, maybe this is the question already, but I did not find it ..
Problem
We have a large enterprise application with many entry points. The application contains a part like:
- Server
- Desktop client
- Some console utilities
- .NET API (standalone assembly with a root class called
MyAppAPI
) - COM API (same, separate assembly, you can access the API from, for example, VBScript,
Set api = CreateObject("MyApp.MyAppAPI")
- Java API (again)
- Message API (a separate assembly used to communicate between layers through message queues)
We use Unity as the DI container in this application. Everything in Server / DesktopClient / Console utilities, etc. - there are very specific entry points, so we just initialize the composite root object there, initialize the tree of objects / dependencies, and everything works like a charm. Their problem is with our APIs.
# 1
How to work with DI in libraries / frames?
From the above link:
Composition root is a component of the application infrastructure.
Only applications should have composition roots. Libraries and frameworks should not.
Yes, it's cool, but .. I want to use DI in my API, it's huge! How to deal with others?
# 2
We have dependencies that should preferably be single point (for example, some factories that control the lifetime of created objects). But we can create multiple instances of API objects, how to share these singleton instances between them? Moreover, we can create several instances of .NET API objects and one or several instances of COM API objects in the same domain (if you want, I can explain in the commentary when this is possible).
What i have now
As I said, there are no problems with applications, the problem exists in libraries (APIs). So what I have now
- I have a
ShellBase
class - this class contains the
_Shells
static field and the public static methods Get
and Release
- there is a hierarchy between containers (for example, API containers are inherited from MessagingAPI, Server and DesktopClient containers, inherited from a .NET API container, etc.).
- when someone requests a new shell (via the
Get
method), ShellBase
checks to see if there is such a container (or a super container from a subclass) and returns this instance. Or creates a new
I donβt like it, but itβs the best I can imagine right now.
Possible Solution
Create something like APIFactory
that will create our API objects, but looks too complicated for end users. I donβt want to write in user documentation: "Please create and save an APIFactory instance first, then you can create API instances using this factory." This is ugly. Our users should only write var api = new API()
and use it.
So guys, what do you think?