我正在创建一个包含以下部分的 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/