【问题标题】:Is it possible to inject into asp.net web api model classes是否可以注入asp.net web api模型类
【发布时间】:2012-10-23 00:36:03
【问题描述】:

我在 asp.net web api 中的模型类上实现 IValidatableObject。一些对象需要访问数据存储库才能执行完整验证。

如何在调用 IValidatableObject.Validate 之前解决 DAL 依赖关系 - 或者是否有其他方法可以解决 Validate 调用中的依赖关系?

请注意,我正在尝试使用 autofac,根据 Inject into asp.net web api model with autofac,但在我看来,模型没有使用依赖解析器调用。

【问题讨论】:

标签: c# asp.net-web-api dependency-injection dependencies


【解决方案1】:

你的模型类不应该是依赖注入的一部分。他们也不应该对自己的验证负责(尽管用验证属性来装饰它们——这只是元数据——就可以了)。

而是定义一个适当的抽象来进行验证。例如,定义这个抽象:

public interface IValidator<T>
{
    ValidationResult Validate(T instance);
}

通过这种方式,您可以针对特定类型对 IValidator&lt;T&gt; 接口进行零个、一个或多个实现,并且您可以使用 Autofac 非常有效地注册这些。

当一个类型没有验证时,你可以让容器传回一个默认的-empty-实现:

// Implementation of the Null Object pattern
public class EmptyValidator<T> : IValidator<T>
{
    public ValidationResult Validate(T instance)
    {
        return ValidationResult.ValidResult;
    }
}

当一个类型定义了多个验证器时,您可以将它们包装在一个组合中:

// Implementation of the Composite pattern
public class CompositeValidator<T> : IValidator<T>
{
    private readonly IEnumerable<Validator<T>> col;

    public CompositeValidator(IEnumerable<Validator<T>> col)
    {
        this.col = col;
    }

    public ValidationResult Validate(T instance)
    {
        ValidationResult total = ValidationResult.ValidResult;

        foreach (var validator in this.col)
        {
            var result = validator.Validate(instance);
            total = ValidationResult.Append(total, result);
        }

        return total;
    }
}

不要将IValidator&lt;T&gt; 直接注入到您的Web API 控制器中,而是创建一个环绕您的IRepository&lt;T&gt; 接口的装饰器。这样您就可以添加验证行为,而无需更改您的存储库。这样的实现可能如下所示:

public class ValidationRepositoryDecorator<T>
    : IRepository<T>
{
    private readonly IRepository<T> decorated;
    private readonly IValidator<T> validator;

    public ValidationRepositoryDecorator(
        IRepository<T> decorated,
        IValidator<T> validator)
    {
        this.decorated = decorated;
        this.validator = validator;
    }

    public void Save(T instance)
    {
        var result = this.validator.Validate(instance);

        if (!results.IsValid)
            new ValidationException(result);

        this.decorated.Save(instance);
    }
}

Autofac 允许你为你注册装饰器。

【讨论】:

  • 感谢您提供详细的答案 - 我会因其有用的内容而对其进行投票,但是我有理由希望将验证逻辑从最初实现的位置移开(在 POST 和 PUT 方法的顶部) ) 对于模型类,我还没有准备好放弃 IValidatableObject 的便利性,因为我希望将特定类的所有规则(声明为属性的规则和需要更精细编码的规则)合二为一地点。
  • @Steven - 谢谢你的回答。它也可以与 Unity 一起使用吗?任何提示如何为这种情况设置 Unity?尤其是 Unity 如何使用所有相关的 IEnumerable> 创建 CompositeValidator 的实例?
  • @Tohid:对不起。我对 Unity 没有那么丰富的经验。尝试在 SO 上发布一个新问题。祝你好运
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-08
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 2022-06-13
  • 2017-09-02
相关资源
最近更新 更多