如何使用相同的通用方法来验证不同类型

时间:2018-08-16 06:10:25

标签: c# asp.net asp.net-mvc asp.net-web-api

我有一个接口IValidator,该接口具有通用方法Validate,旨在验证整个应用程序中的不同对象。现在,我正在验证用户的个人资料和登录凭据。问题是,当我尝试验证配置文件或Login类时,即使我尝试验证Login详细信息,它也始终调用该配置文件的方法。这是代码:

IValidator

 public interface IValidator
{
    List<Error> Validate<T>(T request);
}

UserProfileValidator

 public class UserProfileValidator : IValidator 
{
    public List<Error> Validate<T>(T request)
    {
       //Code for profile validation
    }
}

UserLoginValidator

 public class UserLoginValidator: IValidator 
{
    public List<Error> Validate<T>(T request)
    {
       //Code for login validation
    }
}

UserService

   private readonly IValidator _validator; 

   public UserService(IValidator validator)
    {
        _validator = validator;
    }


 public async Task<Response> Login(UserDetail userDetail)
 {
     //this is supposed to validate login details, but validates profile instead
        var errors = _validator.Validate(userDetail); 
 }

public async Task<Response> UpdateProfile(Profile profile)
 {
        var errors = _validator.Validate(profile);
 }

请指导。谢谢

4 个答案:

答案 0 :(得分:2)

我正在发布此消息,尽管它可能无法解决OP的问题。

根据您所说的使用AutoFac。

服务:

builder.RegisterType<UserService>().As<IUserService>();

验证者:

builder.RegisterAssemblyTypes(typeof(DependencyBuilder).Assembly).Where(t => t.Name.EndsWith("Validator")).AsImplementedInterfaces().InstancePerLifetimeScope(); 

在查看如何注册UserService时,您没有为其构造函数提供特定的IValidator参数,我认为这是AutoFac继续使用UserProfileValidator的原因。从逻辑上讲,UserService将如何知道在运行时使用IValidator的哪种实现?

我经常使用以下内容为构造函数指定参数。

builder
    .Register(r => new UserService(r.Resolve<IValidator>()))
    .As<IUserService>()
    .InstancePerRequest();

但是问题在于,如果DI可以解决IValidator,那么它仍然不是特定的。

我建议重新设计代码,因为我认为您当前的设计不允许UserService同时使用UserProfileValidatorUserLoginValidator

可能为每个视图模型分配IValidator是一个更好的方法,这样每个视图模型都有自己的IValidator实现,然后您可以执行类似var errors = viewModel.Validate();的事情。

答案 1 :(得分:0)

您应该将界面更改为:

public interface IValidator<T>
{
    List<Error> Validate(T request);
}

答案 2 :(得分:0)

您必须在默认的DI容器或Autofac中使用某些依赖项注入注册。请提供您的操作细节。

您的接口不是通用的,这意味着您的依赖项注入容器正在为同一接口注册多个实现,而在您注入它时,它将采用最后一个实现。

将界面更改为

public interface IValidator<T>
{
    List<Error> Validate(T request);
}

并注入服务IValidator<UserDetail>和另一个IValidator<Profile>,因此从本质上讲,存在使用同一接口的不同验证器。

当实现是泛型时,可以使用泛型,但是在您的情况下,每个验证器都是不同的,因此DI需要确切知道要使用哪个验证器。

在autofac中,您应该有类似的东西

builder.RegisterType<UserLoginValidator>().As<IValidator<UserDetails>>();
builder.RegisterType<ProfileValidator>().As<IValidator<Profile>>();

答案 3 :(得分:0)

感谢大家的帮助,它确实帮助我解决了这个问题。我使用Autofac的键控服务将两个验证器都注册为IValidator,然后根据需要通过索引进行解析。

查看此: https://autofaccn.readthedocs.io/en/latest/advanced/keyed-services.html