简体   繁体   中英

Why should I use Interface type of object in Constructor instead of Actual Class Object

I've outsourced my enterprise level project to a freelancer and I got a quite good setup too. But now that contract has finished and the person has also moved to a new technology, in other words not willing to extend the contract. Now I'm looking into this code on myself. I do have a 2 3 years of background in C# and MVC. Below is a rough idea of my application architecture. Hopefully I've tried my best to abstract the architectural details of an enterprise level application. Please let me know if you need further brief on any of the questions.


All my Entities are defined as C# POCO classes as:

public class Product : BaseEntity
{
   public int ProductId { get; set; }
   public string ProductName { get; set; }
}

Now I've a IDbContext like as :

public interface IDbContext : IDisposable
{
    IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity;      
}

Base Entity is a Partial POCO class that each POCO entity is inheriting. Here is a class that implements this IDBContext as:

public class MyObjectContext : DbContext, IDbContext
{
    public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
    {
        return base.Set<TEntity>();
    }
}

Now I've defined a IDbContextFactory that is responsible for providing the DBContexts as :

public interface IDbContextFactory
{
    Lazy<IDbContext> CreateDbContext();
}

The class implementing this IDBContextFactory interface is having below structure :

public class MyDbContextFactory : IDbContextFactory
{
    public MyDbContextFactory(string dbConnectionString)
    {
        _dbConnectionString = Settings.DbConnectionString;
        _dbContext = CreateDbContext();
    }

    public IDbContext CreateDbContext()
    {
        IDbContext dbContext = new IDbContext(() => CreateNewContext());
        return dbContext;
    }

    private MyObjectContext CreateNewContext()
    {
        return new MyObjectContext (_dbConnectionString);
    }
}

Here IRepo Pattern comes into role as:

public partial interface IRepository<T> where T : BaseEntity
{
    T GetById(object id);
}

Now the Repository class implementing this Interface is as below :

public partial class EfRepository<T> : IRepository<T> where T : BaseEntity
{
    private readonly Lazy<IDbContext> _dbContext;
    private readonly IDbContextFactory _dbContextFactory;
    private readonly Lazy<ObjectStateManager> _objectStateManager;

    public EfRepository(IDbContextFactory dbContextFactory)
    {
        _dbContextFactory = dbContextFactory;
        _dbContext= _dbContextFactory.CreateDbContext();
        _objectStateManager= new Lazy<ObjectStateManager>(() => ((IObjectContextAdapter)_dbContext.Value).ObjectContext.ObjectStateManager);
    }

    public T GetById(object id)
    {
        return this.Entities.Find(id);
    }
}

Till now we are done with the Infrastructure level setup for DB Access Management. Now the thing is to utilize this setup into Controllers(as I'm having directly accessing Repositories from Controllers) to as below :

public class CountryController: BaseController
{
    private readonly Lazy<IRepository<Country>> _countryRepository;

    public CountryController(Lazy<IRepository<Country>> countryRepository)
    {
        _countryRepository = countryRepository;
    }

    public Country GetCountryById(int id)
    {
        Country country = _countryRepository.Value.GetById(id);

        if (country != null)
            return country;
        else
            return null;
    }

Hopefully all above is clear. Now here are the some questions that I need to be answered :

1) Why we are having this layered flow like as:

IDBContext -> IDBContextFactory -> IRepository <T>

and then finally using this IRepository into Controllers for accessing Data objects. In other words why we are relying on Interfaces instead of actual Class Objects while implementing Constructor Injection for Country Controller ?

2) Is this the correct approach for a Enterprise level Application as it should be much scalable for future purpose. If there is any other then I would be glad to know about that ?

3) In Controller's constructor I've used Lazy>, so what's the purpose of this Lazy and is it beneficial actually If yes then in what way ?

This is Design Pattern. And it is called Dependency Injection .

The EfRepository class demands its dependencies be injected using its constructor—this is known as constructor injection . We could also allow the dependencies to be injected through a public property, known as setter injection .

One of most important features of the MVC pattern is that it enables separation of concerns. We want the components in our application to be as independent as possible and to have as few interdependencies as we can manage.

In our ideal situation, each component knows nothing about any other component and only deals with other areas of the application through abstract interfaces. This is known as loose coupling , and it makes testing and modifying our application easier. Interfaces help us decouple components.

What we need is a way to obtain objects that implement a given interface without having to create the implementing object directly. The solution to this problem is called dependency injection (DI), also known as Inversion of Control (IoC).

DI is a design pattern that completes the loose coupling we started by adding the interface.

Quotes are copied from the 3rd chapter of this book.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM