cantdoanything33
cantdoanything33

Reputation: 179

Autofac constructor/property injection (DbContex

I am starting to work with DI/IoC and I have some troubles understanding all the concepts.

I have chosen Autofac because it seems it's one of the few that supports both .Net 4.6+ and .Net Core. It seems it also most widely used.

1) Constructor injection - for e.g. in Controllers or my WCF services I understand that it is impossible to do constructor injection to an object that I am instantiating in my code, meaning it is not automatically instantiated.

2) Property injection I would like to do something similar to how you do it in Ninject:

[Inject]
public IWeapon Weapon { get; set; }

And as I understund, in Autofac. it is equivelanet to:

builder.RegisterType<Weapon>().As<IWeapon>().PropertiesAutowired();

1. Now, why is the constructor injection the preferred way?

For example, I have:

Those factories, are just one-liners that should do something like (from another IoC):

public class DataRepositoryFactory : IDataRepositoryFactory
{
    T IDataRepositoryFactory.GetDataRepository<T>()
    {
        return ObjectBase.Container.GetExportedValue<T>();
    }
}

Some methods require both, some do not. Doing something like:

public SampleControllerOrManager(IUnitOfWork unitOfWork, IRepositoryFactory repositoryFactory, IBusinessEngineFactory engineFactory)

seems like a waste of resources.

I understand that this helps with testing (?).

But this looks cleaner:

public SampleControllerOrManager(IUnitOfWork unitOfWork)

[Inject]
public IRepositoryFactory RepositoryFactory { get; set; }

[Inject]
public IBusinessEngineFactory EngineFactory { get; set; }

2. Injecting Entity Framework DbContext into the repositories

I want to register the context with the Container and have that injected into the object constructors of the UnitOfWork and the Repository's. I want to be sure the same instance is injected into all the objects. How do I do it in Autofac?

    public class Repository : IRepository {
        //context injected here
        public Repository (DbContext context){ ... }
    }

    public class Manager {
        public void SomeMethod(){
            IRepository = RepositoryFactoryGetDataRepository<ISomeTypeRepository>
        }
    }

Upvotes: 0

Views: 581

Answers (1)

Laurent De Cant
Laurent De Cant

Reputation: 503

Constructor Injection

Constructor injection is the preferred way because it makes them obvious. You can't instantiate the class if you do not provide the required dependencies.

With property injection dependencies are hidden and you could instantiate the class with some missing injections which could lead you to believe that the class is fully initialized and ready to be used. Eventually, you could get an error if you try use a functionality that needs a missing dependency.

Instance Scope

To be sure that the same instance is injected, you could register your DbContext as Singleton. For example:

var builder = new ContainerBuilder();
builder.RegisterType<DbContext>().SingleInstance();

Or, depending on your needs, you could register it using the Instance Per Request scope:

var builder = new ContainerBuilder();
builder.RegisterType<DbContext>().InstancePerRequest();

Note: You may find this article written by Martin Fowler useful.

Upvotes: 1

Related Questions