您的模型类不应该是依赖注入的一部分。他们也不应该为他们自己的验证负责(尽管用验证属性来装饰它们 - 这仅仅是元数据 - 将是很好的)。
而是定义一个适当的抽象来进行验证。例如,定义了这个抽象:
public interface IValidator<T>
{
ValidationResult Validate(T instance);
}
这样你就可以拥有的IValidator<T>
接口特定类型的零个,一个或多个实现,并且可以与Autofac都非常有效注册此。
当一个类型没有验证,就可以让容器传回一个默认的空白 - 实现:
// 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<T>
到您的Web API控制器,创建一个装饰器,包装IRepository<T>
接口。通过这种方式,您可以添加验证行为,而无需更改存储库。这种实现可能如下所示:
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允许您为您注册装饰器。
在我看来,你会对这个感兴趣:http://aspnetwebstack.codeplex.com/workitem/463我真的需要这个特性来实现。如果你愿意,你也可以为此投票。 – tugberk