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

艾米

我已经将我的企业级项目外包给了自由职业者,并且我也得到了一个很好的设置。但是现在合同已经完成,此人也已经使用了新技术,换句话说,他不愿意延长合同。现在,我正在研究自己的这段代码。我确实有2 3年的C#和MVC背景。下面是我的应用程序体系结构的粗略想法。希望我已尽力抽象出企业级应用程序的体系结构细节。如果您需要任何进一步的简要介绍,请告诉我。


我所有的实体都定义为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;      
}

基础实体是每个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模式在这里的作用是:

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

到现在为止,我们已经完成了数据库访问管理的基础结构级别设置。现在,事情是利用此设置到Controllers中(如下所述,因为我已经直接从Controllers访问存储库):

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运用于Controller中以访问Data对象。换句话说,为什么在为Country Controller实施构造函数注入时依赖接口而不是实际的类对象?

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

3)在Controller的构造函数中,我使用了Lazy>,所以此Lazy的目的是什么,实际上有什么好处?

法哈德·贾比耶夫(Farhad Jabiyev)

这是设计模式。这就是所谓的依赖注入

EfRepository类要求及其依赖使用其构造-这被称为喷射构造注射我们还可以允许依赖项通过称为setter injection的公共属性来注入

MVC模式的最重要特征之一是它使关注点分离成为可能。我们希望应用程序中的组件尽可能独立,并具有我们可以管理的尽可能少的相互依赖关系。

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

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

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

行情从第3章复制本书。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何使用实现父接口的类中的构造函数初始化接口类型的对象?

我应该在构造函数中构建对象吗?

我应该在Android的Date中使用哪个类?

什么时候应该在Python中使用类?

什么时候应该在Java中使用接口?

为什么应该在javabean类中提供public构造函数

我应该在多线程环境中使用对象池,单例或静态方法吗?

我应该在道具中使用哪种TypeScript类型来引用匹配对象?

为什么我不应该在PHP中使用mysql_ *函数?

为什么应该在componentDidMount中而不是在ReactJS中使用getInitialState进行异步请求?

我应该在API上公开接口而不是具体对象吗?

我应该在Angular指令中使用单个对象还是单个值作为属性?

为什么以及何时应该在C中使用指针到指针而不是简单的指针?

为什么我应该在简单的对象配置上使用Angular的依赖注入?

为什么方法返回接口类型的对象?

我应该在ECS中使用静态类吗?

为什么我应该在Flutter中使用Cards?

我应该在UPC中使用哪种网络类型

我应该在React中使用哪种类型的组件:功能组件或类基础组件?

我们应该在PHP中使用“ --->”之类的对象范围吗?

什么时候应该在Z3中使用函数而不是变量?

为什么我的通用类构造函数拒绝接受实现所请求接口的对象

为什么我应该在 Projectile Motion 中使用速度方程而不是位置方程

在哪些情况下,我应该在 EasyMock 的单元测试中使用 Capture 而不是对象?

我应该在 Javascript 中使用多个变量还是单个对象?

为什么构造函数应该在类范围内?

Android - 为什么我们应该在片段中使用 saveInstanceState 包而不是片段参数?

为什么我不能将对象转换为其接口类型?

为什么我应该在异常处理中使用 std::cerr 而不是 std::cout ?