Search code examples
c#asp.net.netdependency-injectionunity-container

Dependency injection to include post-construction actions?


In our solution, we use dependency injection to instantiate instances of a DbContext class which many other services depend on:

var container = new UnityContainer();
container.RegisterType<OurAppDbContext>(new PerThreadLifetimeManager());
// ... A bunch of services that take a new OurAppDbContext as an argument

This successfully results in instantiating a dozen or so services with their own OurAppDbContext instances.

The Problem

The OurAppDbContext constructor (auto-generated by EntityFramework, therefore not editable) is not quite sufficient for our purposes. If we had it our way, every instance would be constructed as such:

OurAppDbContext newDbContext = new OurAppDbContext();
newDbContext.Database.Log += log => Debug.WriteLine(log);
return newDbContext;

Right now, the way we can hook this event is in every constructor of every service that gets one of these instances. e.g.:

public class AdminDataRepository : IAdminDataRepository
{
    private readonly OurAppDbContext _dbContext;
    public AdminDataRepository(OurAppDbContext dbContext)
    {
        _dbContext = dbContext;
        _dbContext.Database.Log += log => Debug.WriteLine(log);
        ...

But we would rather not have this code copy-pasted into 10+ different service constructors as it becomes a maintenance headache, we might miss it in a few places, or they might get out of sync, etc.

Is there a way to instruct the dependency injector to do this to each OurAppDbContext it constructs - before it passes it along to whatever service it's constructing that depends on it?


Solution

  • You can make the registration using a factory delegate:

    container.RegisterFactory<OurAppDbContext>(c =>
        {
            OurAppDbContext newDbContext = new OurAppDbContext();
            newDbContext.Database.Log += log => Debug.WriteLine(log);
            return newDbContext;
        },
        new PerThreadLifetimeManager());