Skip to content

To better-integrate with DI, developers should be able to use an IServiceProvider from a Configuration #2709

Open
@craigfowler

Description

@craigfowler

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 with System.IServiceProvider
  • Move the property for the objects factory from the static Environment object to the Configuration 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions