简体   繁体   English

为什么我应该在构造函数中使用接口类型的对象而不是实际类对象

[英]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. 我在C#和MVC方面有2年的背景经验。 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: 我的所有实体都被定义为C#POCO类:

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

Now I've a IDbContext like as : 现在我有一个像以下一样的IDbContext:

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

Base Entity is a Partial POCO class that each POCO entity is inheriting. Base Entity是每个POCO实体继承的Partial POCO类。 Here is a class that implements this IDBContext as: 这是一个实现此IDBContext的类:

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 : 现在我已经定义了一个IDbContextFactory,它负责提供DBContexts:

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

The class implementing this IDBContextFactory interface is having below structure : 实现此IDBContextFactory接口的类具有以下结构:

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: 在这里,IRepo Pattern发挥作用:

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

Now the Repository class implementing this Interface is as below : 现在,实现此接口的Repository类如下所示:

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: 1)为什么我们这样的分层流程如下:

IDBContext -> IDBContextFactory -> IRepository <T>

and then finally using this IRepository into Controllers for accessing Data objects. 然后最终将此IRepository用于控制器以访问Data对象。 In other words why we are relying on Interfaces instead of actual Class Objects while implementing Constructor Injection for Country Controller ? 换句话说,为什么我们在为Country Controller实现Constructor Injection时依赖于Interfaces而不是实际的Class Objects?

2) Is this the correct approach for a Enterprise level Application as it should be much scalable for future purpose. 2)这是企业级应用程序的正确方法,因为它应该具有很大的可扩展性以用于将来的目的。 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 ? 3)在Controller的构造函数中我使用了Lazy>,那么这个懒惰的目的是什么呢?它实际上是否有益如果是,那么以什么方式?

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 . EfRepository类要求使用其构造函数注入其依赖项 - 这称为构造函数注入 We could also allow the dependencies to be injected through a public property, known as setter injection . 我们还可以允许依赖项通过公共属性注入,称为setter注入

One of most important features of the MVC pattern is that it enables separation of concerns. MVC模式最重要的特征之一是它能够分离关注点。 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),也称为控制反转 (IoC)。

DI is a design pattern that completes the loose coupling we started by adding the interface. DI是一种设计模式,它通过添加接口来完成我们开始的松散耦合。

Quotes are copied from the 3rd chapter of this book. 行情从第3章复制本书。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在接口中将参数化的构造方法对象分配给类类型属性协定 - How to assign parameterized constructor object to class type property contract in interface 为什么我应该返回 ActionResult 而不是对象? - Why should I return ActionResult instead of object? 为什么接口返回 object 而不是泛型参数类型? - Why does interface return object instead of generic parameter type? 为什么我们从接口而不是类创建对象实例? - Why we do create object instance from Interface instead of Class? 使用反射获取实际的返回类型表单Task <List<Dictionary<string,object> &gt;&gt;代替对象 - Use reflection to get actual return type form Task<List<Dictionary<string,object>>> instead of object C# 静态类:我应该将对象传递给构造函数吗? - C# static class: should I pass the object to the constructor? MongoDB错误:无法确定要反序列化为接口类型的对象的实际类型 - MongoDB error: Unable to determine actual type of object to deserialize for interface type 如果将实际对象类型分配给接口类型,是否可以获取它? - Is it possible to get the actual object type if it is assigned to an interface type? 对事件使用对象类型而不是实际类型的原因是什么? - What's the reason of using the Object type instead of an actual type for events? 为什么我不能将对象转换为其接口类型? - Why cannot I cast an object to its interface type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM