繁体   English   中英

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

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

我已将我的企业级项目外包给自由职业者,我也得到了很好的设置。 但是现在合同已经完成,而且这个人也转向了新技术,换言之,不愿意延长合同。 现在我正在研究这个代码。 我在C#和MVC方面有2年的背景经验。 下面是我的应用程序架构的粗略概念。 希望我尽力抽象出企业级应用程序的架构细节。 如果您需要进一步了解任何问题,请与我们联系。


我的所有实体都被定义为C#POCO类:

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

现在我有一个像以下一样的IDbContext:

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

Base Entity是每个POCO实体继承的Partial POCO类。 这是一个实现此IDBContext的类:

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

现在我已经定义了一个IDbContextFactory,它负责提供DBContexts:

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

实现此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);
    }
}

在这里,IRepo Pattern发挥作用:

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

现在,实现此接口的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);
    }
}

到目前为止,我们已完成数据库访问管理的基础架构级别设置。 现在的问题是将此设置用于控制器(因为我直接从控制器访问存储库)如下所示:

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;
    }

希望以上都清楚。 现在这里有一些我需要回答的问题:

1)为什么我们这样的分层流程如下:

IDBContext -> IDBContextFactory -> IRepository <T>

然后最终将此IRepository用于控制器以访问Data对象。 换句话说,为什么我们在为Country Controller实现Constructor Injection时依赖于Interfaces而不是实际的Class Objects?

2)这是企业级应用程序的正确方法,因为它应该具有很大的可扩展性以用于将来的目的。 如果还有其他的话我会很高兴知道吗?

3)在Controller的构造函数中我使用了Lazy>,那么这个懒惰的目的是什么呢?它实际上是否有益如果是,那么以什么方式?

这是设计模式。 它被称为依赖注入

EfRepository类要求使用其构造函数注入其依赖项 - 这称为构造函数注入 我们还可以允许依赖项通过公共属性注入,称为setter注入

MVC模式最重要的特征之一是它能够分离关注点。 我们希望应用程序中的组件尽可能独立,并且尽可能减少相互依赖性。

在我们理想的情况下,每个组件对任何其他组件一无所知,只通过抽象接口处理应用程序的其他区域。 这称为松耦合 ,它使我们的应用程序的测试和修改更容易。 接口可以帮助我们解耦组件。

我们需要的是一种获取实现给定接口的对象而无需直接创建实现对象的方法。 该问题的解决方案称为依赖注入 (DI),也称为控制反转 (IoC)。

DI是一种设计模式,它通过添加接口来完成我们开始的松散耦合。

行情从第3章复制本书。

暂无
暂无

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

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