Constructor Dependency Injection in Base Class

限于喜欢 提交于 2019-12-04 19:28:59

问题


i'm building a repository base class with Entity Framework where all Entities repository will inherit. I want to inject the DatabaseContext in base class using Dependency Injection using Ninject. I think the Constructor Injection is the right way, but doing this with Constructor Injection in derived class I will must to pass parameter to constructor in base class and I don't want it. Therefore, a Setter Injection is more appropriate?

Here's my code:

public abstract class BaseRepository<TEntity> : IDisposable 
    where TEntity : class
{
    private readonly DatabaseContext _databaseContext;

    protected BaseRepository(DatabaseContext databaseContext)
    {
        this._databaseContext = databaseContext;
    }
}

Using Constructor Injection in the above example, in my derived class I will must to pass databaseContext object to base class, I don't like to doing this to all my derived class:

public class UsuarioRepository : BaseRepository<IUsuario>,
    IUsuarioRepository
{
    public UsuarioRepository(DatabaseContext databaseContext)
        : base(databaseContext)
    {
    }
}

Setter Injection instead of Constructor Injection is a good way to solve that? What is the best way?

Update:

Using Setter Injection my derived class's will not have constructors:

public class UsuarioRepository : BaseRepository<IUsuario>, IUsuarioRepository
{
}

My Context is only one in all application. I don't need derived class to pass context object, but i like to inject it in base class to using mocks for tests in future.

I Solve the problem:

Sorry, I'm confusing with the question, but i'm solving my problem building a Factory:

public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity>
   where TEntity : class
{
    private readonly ContextFactory _contextFactory = new ContextFactory();

    protected DatabaseContext CurrentContext
    {
        get
        {
            return this._contextFactory.GetCurrentContext();
        }
    }
 }

And my derived class will look like that:

public class UsuarioRepository : BaseRepository<IUsuario>, IUsuarioRepository
{
}

And My Factory like that:

public class ContextFactory
{
    public DatabaseContext GetCurrentContext()
    {
        return new DatabaseContext();
    }
}

回答1:


Property Injection implies that the dependency is optional, while Constructor Injection implies that the dependency is required. Choose a pattern accordingly.

In more than 95% of the cases Constructor Injection is the correct pattern. What about it don't you like?




回答2:


I don't think there is a "best way".

Constructor and setter injection are not exactly equivalent, as setter injection provides you a little more flexibility. Here is how I choose between the two:

Lets say you create an object A, and A needs a B object to work. Question to be asked is: Is it possible for A to exist/be instantiated without having a B associated with it? Is it a valid state for the A object to not have a B? Sometimes it does not make sense for A to ever have a null B, then constructor injection is the better solution. If, it is ok for B to be assigned to A later on and not necessarily at construction time, then go with setter injection. All this depends on the domain that you are trying to model, and the answers will change from situation to situation.




回答3:


Really, I can't see any problem with passing a parameter to a base class. But if that's an absolute requirement, you could always do this:

public abstract class BaseRepository<TEntity> : IDisposable 
    where TEntity : class
{
    protected BaseRepository()
    {
    }

    protected abstract DatabaseContext GetContext();
}

Now your derived classes can look like this:

public class UsuarioRepository : BaseRepository<IUsuario>,
    IUsuarioRepository
{
    private DatabaseContext _databaseContext;

    public UsuarioRepository(DatabaseContext databaseContext)
    {
        _databaseContext = databaseContext;
    }

    protected override DatabaseContext GetContext()
    {
        return _databaseContext;
    }
}

Now you can have constructor injection without passing a parameter to the base constructor. But it's really the same thing.

I honestly don't like the idea of setter injection, because it looks like the DatabaseContext is a required dependency. For required dependencies, do constructor injection. If it were optional, then by all means, go ahead and do setter injection.

EDIT:

Due to our long conversation in the comments, I have a much better understanding of what you're trying to accomplish.

If you want to decouple your derived classes from the DatabaseContext, you might be better off designing it differently. It is hard to decouple a derived class from its base class's dependencies, and if you think they should be decoupled, then you will have better design not using inheritance at all.

public class BaseRepository<TEntity> : IDisposable 
    where TEntity : class
{
    public BaseRepository(DatabaseContext context)
    {
    }
}

Now your derived classes (which would not be derived anymore) would look like this:

public class UsuarioRepository : IUsuarioRepository
{
    public UsuarioRepository(BaseRepository<IUsario> repository)
    {
    }

    // Implement other methods here
}

Now you can have your one base class that uses the DatabaseContext, and your derived classes are no longer dependent on it.




回答4:


All the three ways 1. Contstructor, 2. Setter and 3. Interface Injection has their advantages and disadvantages its depend on situation which one to use. If i would be in your place i would have gone with setter though interface can be a good choice also.

Request you to go through this article http://www.devx.com/dotnet/Article/34066



来源:https://stackoverflow.com/questions/6138924/constructor-dependency-injection-in-base-class

工具导航Map