实例化泛型类错误
本文关键字:错误 泛型类 实例化 | 更新日期: 2023-09-27 18:18:09
我正在创建c# windows应用程序,并使用FluentValidation来验证视图模型。在每个表单中,我总是创建这样的验证方法:
private bool ValidateCustomer(CustomerViewModel customerVM)
{
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customerVM);
if (!results.IsValid)
{
StringBuilder errorMessage = new StringBuilder("Data Validation Checking Error:'n");
foreach (var failure in results.Errors)
{
errorMessage.AppendLine("- " + failure.ErrorMessage);
}
MessageBox.Show(errorMessage.ToString(), "Exclamation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
return true;
}
public class CustomerValidator : AbstractValidator<CustomerViewModel>
{
public CustomerValidator()
{
RuleFor(c => c.Code).NotEmpty();
RuleFor(c => c.Name).NotEmpty();
}
}
我想创建通用ValidationHelper类,这样我就不会在每种形式中编写相同的验证代码(只是不同的验证器和视图模型类),例如:ValidationHelper<MyValidator, MyViewModel>.Validate()
。我只是替换MyValidator和MyViewModel类为其他形式。当创建这个泛型类时,我在实例化验证器类时遇到了问题。
public static class ValidatorHelper<T, V>
where T : class, new()
where V : class, new()
{
public static bool Validate(T t, V n)
{
T validator = new T();
ValidationResult results = validator.Validate(n); // <--- error on this line
if (!results.IsValid)
{
StringBuilder errorMessage = new StringBuilder("Data Validation Checking Error:'n");
foreach (var failure in results.Errors)
{
errorMessage.AppendLine("- " + failure.ErrorMessage);
}
MessageBox.Show(errorMessage.ToString(), "Exclamation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
return true;
}
}
如何解决这个问题?
:
根据@JonSkeet和@dbc的建议,我将ValidatorHelper修改为:
public static class ValidatorHelper<T, V>
where T : AbstractValidator<V>, new()
where V : class, new()
{
public static bool Validate(V v)
{
T validator = new T();
ValidationResult results = validator.Validate(v);
if (!results.IsValid)
{
StringBuilder errorMessage = new StringBuilder("Data Validation Checking Error:'n");
foreach (var failure in results.Errors)
{
errorMessage.AppendLine("- " + failure.ErrorMessage);
//log.Message("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
}
MessageBox.Show(errorMessage.ToString(), "Exclamation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
return true;
}
}
我没有在public static bool Validate(V v)
上使用T,因为它将在其中实例化。然后在表单上写上:
if (ValidatorHelper<CustomerValidator, CustomerViewModel>.Validate(customerVM))
多亏你们俩,我才能解决这个问题,我真的很感激。
您正在尝试将CustomerValidator
引用分配给T
类型的变量。如果T
是StringBuilder
之类的呢?
从根本上说,你的ValidationHelper
声称是通用的,但然后是特定于CustomerValidator
的,这似乎很奇怪。
如果不知道FluentValidation库,我们就不能真正知道CustomerValidator
是做什么的——比如它实现了Validator<Customer>
吗?我突然想到,您可能希望将验证器传递到Validate
方法或ValidatorHelper
构造函数中。(我强烈怀疑您想要摆脱和的静态修饰符-如果方法是静态的,它就不能在基类中实现抽象方法…如果类是静态的,它甚至不能指定基类)
基本上,您需要考虑:
- 关于
CustomerValidator
应该知道什么?可能不是是一个通用的助手类。 - 应该如何创建验证器?选项:
- helper本身(可能使用
new()
约束) - 创建helper实例的调用者,假设你要有一个实例
- 调用
Validate
方法
- helper本身(可能使用
你可能想要这样的东西:
// No constraint on V - why would you need one?
public class ValidatorHelper<T, V> : AbstractValidator<V>
where T : AbstractValidator<V>
{
public bool Validate(T validator, V value)
{
ValidationResult results = validator.Validate(value);
if (!results.IsValid)
{
StringBuilder errorMessage = new StringBuilder("Data Validation Checking Error:'n");
foreach (var failure in results.Errors)
{
errorMessage.AppendLine("- " + failure.ErrorMessage);
}
MessageBox.Show(errorMessage.ToString(), "Exclamation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
return true;
}
}
一个问题是您的约束没有表明T
派生自CustomerValidator
:
where T : class, CustomerValidator, new()
但是CustomerValidator
到底是什么?它是一些抽象基类,将为每个验证需求子类化?如果是这样,旧代码中的new CustomerValidator()
将无法工作。
如果CustomerValidator
是某个新创建的抽象基类,为了清晰起见,您可以考虑提取一个接口,如下所示:
public interface IValidator<V>
{
ValidationResult Validate(V data);
}
基本上,这是一个验证任何东西的类的接口,在您的ValidationResult
对象中返回结果。
一旦有了返回验证结果的标准接口,静态帮助器就变成了:
public static class ValidatorHelper<T, V>
where T : class, IValidator<V>, new()
where V : class, new()
{
public static bool Validate(T t, V n)
{
T validator = new T();
ValidationResult results = validator.Validate(n);
if (!results.IsValid)
{
StringBuilder errorMessage = new StringBuilder("Data Validation Checking Error:'n");
foreach (var failure in results.Errors)
{
errorMessage.AppendLine("- " + failure.ErrorMessage);
}
MessageBox.Show(errorMessage.ToString(), "Exclamation", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
return true;
}
}