C# 如何使用相同的泛型方法验证不同的类型
我有一个界面IValidator,它有一个通用的方法Validate,用于验证应用程序中的不同对象。目前,我正在验证用户的配置文件和登录凭据。问题是,当我尝试验证配置文件或登录类时,它总是调用配置文件的方法,即使我尝试验证登录详细信息。代码如下: 幻灯机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请求); } 用户档案验
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();