entity-framework - 在类库中注册容器(IoC)?

标签 entity-framework dependency-injection repository-pattern ioc-container simple-injector

我正在创建一个包含以下部分的 n 层应用程序。

  • MyApp.DAL - 数据访问层(EF 5、SQL 后端)
  • MyApp.BLL - 业务层
  • MyApp.WcfService - 服务层
  • MyApp.WpfClient - 前端
  • MyApp.Models 是一个包含所有 POCO 的共享项目。

我将通过每一层给出一个“国家”实体的例子。首先是模型。请注意,StatefulObject 将帮助我从断开连接的客户端跟踪实体状态(根据 Julia Lerner 的编程 EF 第二版第 18 章)。

public class Country : StatefulObject
{
    [Key]
    [StringLength(2)]
    public string Code { get; set; }
    [Required]
    [StringLength(50)]
    public string Name { get; set; }
}

在 DAL 中,我有一个 ICountryRepository(基本 CRUD)和一个 CountryRepository。这是构造函数。

public class CountryRepository : ICountryRepository, IDisposable
{
    MyDbContext _db;

    public CountryRepository()
    {
        _db = new MyDbContext();
    }

    //Implement ICountryRepository (basically CRUD), etc...
}

我的 BLL 有一个 ICountryLogic、CountryLogic、IBusinessLayer 和 BusinessLayer,如下所示:

public class CountryLogic : ICountryLogic
{
    ICountryRepository _countryRepository;

    public CountryLogic(ICountryRepository countryRepository)
    {
        _countryRepository = countryRepository;
    }

    //implement ICountryLogic members, etc...
}

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer()
    {
        CountryLogic = new CountryLogic(new CountryRepository());
    }
}

然后是一个实例化新业务层并执行如下操作的示例服务方法:

public class CountryService : ICountryService
{
    public IEnumerable<Country> GetAll()
    {
        IBusinessLayer bl = new BusinessLayer();
        return bl.CountryLogic.GetAll();
    }

    //implement other service operations
}

然后 WPF 客户端就可以像这样使用服务了:

CountryServiceClient countryService = new CountryServiceClient();

var countries = countryService.GetAll();

现在,在将 WCF 服务放在 BLL 和 WPF 前端之间之前,我的 WPF 前端可以只使用依赖注入(inject),我不会有这种丑陋:

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer()
    {
        CountryLogic = new CountryLogic(new CountryRepository());  // <<<< UGLY HERE
    }
}

相反,我会像这样使用 DI 和构造函数注入(inject):

public class BusinessLayer : IBusinessLayer
{
    public ICountryLogic CountryLogic { get; set; }

    public BusinessLayer(ICountryLogic countryLogic)
    {
        CountryLogic = countryLogic;
    }
}

那么只要在WPF中的容器中注册接口(interface)和实现即可。我的问题是如何在类库(在 BLL 中)中注册它们?由于类库中没有组合根或入口点,我不确定该怎么做。我正在使用 SimpleInjector。

或者,我可以在 Wcf 服务中使用 DI,但这需要该服务具有对 DAL 的引用,以便它可以将 ICountryRepository 注册到 CountryRepository。这似乎不对。服务层应该只引用BLL,这就是为什么我要在BLL中设置DI。谢谢。

最佳答案

在我看来,您在这里缺少一些抽象。 WPF 客户端不应该关心您在两者之间放置 WCF 服务这一事实。例如,而不是相当丑陋的 XXXService类(例如 CountryService ),请考虑通过线路发送命令和查询消息。这样你就可以定义一个简单的 ICommandHandler<TCommand>IQueryHandler<TQuery, TResult> WPF 客户端可以依赖的接口(interface)。在那种情况下,它不必知道它是否通过网络进行通信。这些抽象还提供了添加横切关注点(作为装饰器)的可能性,例如 circuit breaker design pattern ,这在处理连接不可靠的客户端时非常有用(对查询尤其有用)。对于发送命令,您可能最好使用队列,但这可以作为 ICommandHandler<TCommand> 上的装饰器实现。界面也是如此。

以下是描述这些概念的一些文章:

关于entity-framework - 在类库中注册容器(IoC)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14607446/

相关文章:

c# - 父对象在 EntityState.Unchanged 中,但它仍然插入到数据库中

c# - Entity Framework 连接池 : how to inject UserId into SQL Servers session_context?

eclipse - 是否可以在 Luna (Eclipse e4) 上导入的 3.x 基础 Eclipse 代码中使用依赖注入(inject) (DI)

Spring依赖注入(inject)带注释的Aspect

c# - 如何在每个请求上从 IoC 容器解析 Web API 消息处理程序/DelegatingHandler

c# - 删除实体而不在通用存储库模式 Entity Framework 中获取它

model-view-controller - 数据库和模型之间是否应该有一个抽象层?

entity-framework - 获取 RESTful 请求看到的返回计数

c# - 无需创建 .edmx 的 Entity Framework

java - 从 while 循环创建 Flowable