Description
I recently discovered that NHibernate is more-capable-than-I-had-thought of supporting dependency injection (to a degree as far back as NH4).
Background
The static Environment
object contains an object resolver of sorts: IObjectsFactory
. That objects factory is used to resolve a number of services used by NHibernate, such as connection providers. Looking at the API of that interface, it is almost identical to System.IServiceProvider
, particularly once the obsolete members are removed. I found that - in my own app/usage of NHibernate, I was able to substitute the objects factory with my own custom object which wraps a service provider. If the service provider is able to resolve the desired type then return it, and if not, fall back to Activator.CreateInstance
.
How I'd like to improve upon this
Whilst it would be great in the long-term if NHibernate fully supported DI in all its glory, that's a bit unrealistic to ask for all at once. I think a good first step would be:
- Replace all usages of the
IObjectsFactory
interface withSystem.IServiceProvider
- Move the property for the objects factory from the static
Environment
object to theConfiguration
object- From that point, it will become a part of the immutable session factory
Use-case example
This is just to help show how this is actually helpful in the real world. In my specific use-case, I develop for a multi-tenant application. Each tenant has its own database/connection string, but every tenant/DB has the exact same schema. The running application has just one session factory, but in the configuration we set-up a custom IConnectionProvider
. That connection provider needs to be able to determine which tenant is currently active in order to return a connection to the appropriate database.
The app has services available via DI to determine which tenant is currently active but so far the NHibernate connection provider has needed to achieve all of this statically. Using the default IObjectsFactory
impl, the connection provider can only be instantiated from a public parameterless ctor. In fact with an objects factory which supports DI, the connection provider may have dependencies injected and the static logic can be removed.
Whilst this can already be done (by replacing the objects factory on the Environment
), this would be easier to work with if:
- The interface were the more recognisable service provider
- It were part of the configuration and not a static/singleton environment object
I appreciate that this is a breaking change
Obviously-enough, this change involves alterations to the public API, which would mean it would need to be held for a major version increment.