【问题标题】:DDD: injecting IPrincipal into service and repository layersDDD:将 IPrincipal 注入服务和存储库层
【发布时间】:2015-01-03 05:44:54
【问题描述】:

我目前正在使用 Unity IOC 容器开发基于 DDD 的应用程序,并且需要一种方法将我的自定义 Principal 对象传递到允许进行单元测试的存储库和服务层。这应该怎么做?我目前的想法是在 IPrincipal 类型的服务和存储库类上创建一个属性。然后在 Application_Start 上使用 Unity 设置并传入 Principal。

首先,我的想法是否正确?

二,如果不是在 application_start,这似乎不是正确的地方,因为我需要一个人在注射发生之前先登录,这应该发生在哪里?

三,对于Unity来说,从Thread.CurrentPrincipal或者HttpContext.Current.User中获取Principal的container.RegisterType应该是什么样子的?

【问题讨论】:

  • 贵公司的委托人是什么?看起来您正在使用技术术语污染您的域模型,或者您缺少有界上下文。
  • 主体是指当前登录用户的用户凭证。
  • 这更像是一个反问,让您意识到校长可能不是一个商业术语。该概念应翻译为对您的领域有意义的概念。你会和校长一起做什么样的手术?

标签: domain-driven-design inversion-of-control repository-pattern service-layer


【解决方案1】:

您可以拥有一个 PrincipalDto 类,该类将包含您需要在服务层中使用的相关 IPrincipal 属性,并将值从 IPrincipal 映射到 PrincipalDto。这样您就不需要将 IPrincipal 的引用程序集包含到其他层中。

以下是使用自动映射的示例。

public class PrincipalDto
{
    public UserId { get; set; }
    public Username { get; set; }
    public RoleId { get; set; }
}

public class SomeService
{
    public void SomeServiceMethod(PrincipalDto principal)
    {
        // do work here
    }
}

public class SomeConsumer()
{
    public void SomeConsumerMethod()
    {
        // where User is the IPrincipal object instance
        var principal = Mapper.Map<PrincipalDto>(User);

        var service = new Service();
        service.SomeServiceMethod(principal);
    }
}

【讨论】:

  • 唯一的事情是我试图无缝地让服务层和存储层知道用户而不传递参数。