3

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

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

我将通过每一层给出一个“国家”实体的例子。首先是模型。请注意,StatefulObject 将帮助我跟踪来自断开连接的客户端的实体状态(根据 Julia Lerner 的编程 EF 第 2 版第 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 前端可以只使用依赖注入,我不会有这样的丑陋:

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

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

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

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

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

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

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

4

2 回答 2

4

如我所见,您在这里缺少一些抽象。WPF 客户端不应该关心您在两者之间放置 WCF 服务的事实。例如,不要使用相当丑陋的XXXService类(例如CountryService),而是考虑通过网络发送命令和查询消息。通过这种方式,您可以定义WPF 客户端可以依赖的简单接口ICommandHandler<TCommand>IQueryHandler<TQuery, TResult>在这种情况下,它不必知道它是否通过网络进行通信。这些抽象还提供了添加横切关注点(作为装饰器)的可能性,例如断路器设计模式,这在与连接不可靠的客户端一起工作时非常有用(对查询特别有用)。对于发送命令,使用队列可能会更好,但这也可以作为ICommandHandler<TCommand>接口上的装饰器来实现。

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

于 2013-01-30T16:26:15.020 回答
3

也许您可以尝试static BootStrap在每一层中实现一个方法并链接注册调用(通过每个方法传递容器实例。

Wpf.Client调用Wpf.Service.Bootstrap(container)哪个调用WPF.Bll.Bootstrap(container)...?

这应该会让你继续前进,但我衷心建议你阅读 Stevens 的文章,它们很有意义,并且一旦实现,它们就提供了一个非常灵活的架构。

于 2013-01-30T18:10:28.183 回答