C# 如何使用相同的泛型方法验证不同的类型

C# 如何使用相同的泛型方法验证不同的类型,c#,asp.net,asp.net-mvc,asp.net-web-api,C#,Asp.net,Asp.net Mvc,Asp.net Web Api,我有一个界面IValidator,它有一个通用的方法Validate,用于验证应用程序中的不同对象。目前,我正在验证用户的配置文件和登录凭据。问题是,当我尝试验证配置文件或登录类时,它总是调用配置文件的方法,即使我尝试验证登录详细信息。代码如下: 幻灯机 public interface IValidator { List<Error> Validate<T>(T request); } 公共接口IValidator { 列表验证(T请求); } 用户档案验

我有一个界面IValidator,它有一个通用的方法Validate,用于验证应用程序中的不同对象。目前,我正在验证用户的配置文件和登录凭据。问题是,当我尝试验证配置文件或登录类时,它总是调用配置文件的方法,即使我尝试验证登录详细信息。代码如下:

幻灯机

 public interface IValidator
{
    List<Error> Validate<T>(T request);
}
公共接口IValidator
{
列表验证(T请求);
}
用户档案验证器

 public class UserProfileValidator : IValidator 
{
    public List<Error> Validate<T>(T request)
    {
       //Code for profile validation
    }
}
public类UserProfileValidator:IValidator
{
公共列表验证(T请求)
{
//配置文件验证代码
}
}
用户登录验证器

 public class UserLoginValidator: IValidator 
{
    public List<Error> Validate<T>(T request)
    {
       //Code for login validation
    }
}
public类UserLoginValidator:IValidator
{
公共列表验证(T请求)
{
//登录验证代码
}
}
用户服务

   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);
 }
专用只读IValidator\u验证程序;
公共用户服务(IValidator验证程序)
{
_验证器=验证器;
}
公共异步任务登录(UserDetail UserDetail)
{
//这应该验证登录详细信息,但会验证配置文件
var errors=\u validator.Validate(userDetail);
}
公共异步任务更新配置文件(配置文件)
{
var errors=_validator.Validate(概要文件);
}

请导游。谢谢

您应该将界面更改为:

public interface IValidator<T>
{
    List<Error> Validate(T request);
}
公共接口IValidator
{
列表验证(T请求);
}

您必须对默认DI容器或Autofac使用某种依赖项注入注册。请提供您如何这样做的详细信息

您的接口不是泛型的,这意味着您的依赖项注入容器正在为同一接口注册多个实现,当您注入它时,它正在接受最后一个实现

将界面更改为

public interface IValidator<T>
{
    List<Error> Validate(T request);
}
公共接口IValidator
{
列表验证(T请求);
}
并注入一个服务
IValidator
和另一个
IValidator
,因此本质上存在使用相同接口的不同验证器

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

在autofac中,您应该有

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

虽然这可能不是OP问题的解决方案,但我还是发布了这篇文章

根据您所说,您正在使用AutoFac

服务:

builder.RegisterType<UserService>().As<IUserService>();
看看你是如何注册你的
UserService
的,你没有向它的构造函数提供一个特定的
IValidator
参数,我认为这就是为什么AutoFac一直使用
UserProfileValidator
的原因。从逻辑上讲,
UserService
如何知道在运行时使用
ivalidor
的什么实现

我经常使用以下方法为构造函数指定参数

builder
    .Register(r => new UserService(r.Resolve<IValidator>()))
    .As<IUserService>()
    .InstancePerRequest();
builder
.Register(r=>newuserservice(r.Resolve()))
.As()
.InstancePerRequest();
但问题是DI是否会解决
IValidator
的问题,这仍然不是具体的

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


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

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

见此:

这取决于你如何创建UserService对象。你能告诉我你是如何创建user service对象的吗?很可能你正在将
UserProfileValidator
传递给你的
UserService
因此就有了这个行为。我只是将UserService注入UserController的构造函数,然后调用UpdateProfile或你正在使用的登录方法迪?您如何注册您的
用户服务
,因为它的构造函数需要
IValidator
?是的,我在autofac的帮助下使用DI。下面是代码--builder.RegisterType().As();对于请为您的答案提供一个解释。我尝试了这个方法,但它无法向autofac注册,当我注册这两个验证程序类时,它显示的行为与我在问题中提到的相同。下面是注册所有类的代码,这些类的末尾包含“validator”关键字。以这种方式注册所有验证程序类:=>builder.RegisterAssemblyTypes(typeof(DependencyBuilder.Assembly)。其中(t=>t.Name.EndsWith(“验证程序”)).AsImplementedInterfaces().InstancePerLifetimeScope();好的,那么我将在用户服务中注入单个对象进行验证(IValidator)还是单独的对象?(IValidator和IValidator)好的,那么我将在用户服务中注入单个对象进行验证(IValidator)还是单独的对象?(IValidator和IValidator)
builder
    .Register(r => new UserService(r.Resolve<IValidator>()))
    .As<IUserService>()
    .InstancePerRequest();