7

我有一个User实体,该实体具有一个HasCompletedSecurity属性,该属性指示该特定对象是否User已回答系统要求的安全问题的数量。系统需要的安全问题的数量是可配置的,并且可以从配置文件中检索。类应该如何User访问配置的信息?

我目前有一个IConfigurationService接口,在该接口后面我有使用ConfigurationManager或 Azure 等效项(如果可用)的实现。我已经通过一个静态InjectionService类封装了对我的 DI 容器的访问,并且目前正在解析配置的值,如下所示:

public class User
{
    private static readonly IConfigurationService _configurationService = 
        InjectionService.Resolve<IConfigurationService>();

    public bool HasCompletedSecurity
    {
        get
        {
            // Uses the static _configurationService to get the 
            // configured value:
            int numberOfRequiredResponses = 
                GetConfiguredNumberOfRequiredResponses();

            return this.SecurityQuestionResponses.Count()
                >=
                GetConfiguredNumberOfRequiredResponses();
        }
    }
}

这当然是ServiceLocator 反模式的一个例子,我一点也不喜欢它。静态依赖使得单元测试任何使用这个类的东西都很尴尬。

我正在使用实体框架并从这里得到提示我不想通过 DI 容器传递我的实体以给它们它们的依赖项,所以......我应该如何访问配置的值呢?

编辑:一方面有这个确切的例子(我很欣赏关于它的正确架构的建议),我感兴趣的更大的问题是你如何管理实体对服务的非静态引用?以您永远不需要的方式构建实体的答案是什么?

4

2 回答 2

5

下面是我如何定义 User 类:

public class User
{
    public bool HasCompletedSecurity { get; set; }

    // other members...
}

说真的,这是一个更好的解决方案,因为它沿着时间维度解耦了值。考虑一下:如果用户在 2010 年完成了所有安全问题,而您后来更改了业务规则,那么您是否会让现有用户失效?

在大多数情况下,记录并坚持在过去的某个时间,用户完成了当时有效的安全程序可能更合理。这样,您就不会打扰现有用户。

于 2012-01-31T13:53:18.630 回答
1

您仍然可以使用控制反转的概念,而无需使用任何类型的 IoC 容器或要求在实体的构造函数中使用它。我会使用准策略模式来解决这个问题,并有类似的东西:

public interface ISecurityPolicy
{
    public int MinimumSecurityQuestionResponses { get; }
}

public class User
{
    public void HasCompletedSecurity (ISecurityPolicy security_policy)
    {
         return this.SecurityQuestionResponses.Count()
                     >= security_policy.MinimumSecurityQuestionResponses;
    }
}

这将提供用户必须满足的特定安全策略的责任放在调用者身上,而不是 User 类本身。

从那时起,您可以根据需要提供额外的参数,也许可以将其包装在一个IUserSecurityServiceISecurityPolicy注入服务的参数中,等等。

这仍然是控制反转,但它在方法级别,因为这一种特定方法实际上是唯一关心安全策略/配置的方法。

于 2012-01-31T14:28:25.010 回答