实例化泛型类错误

本文关键字:错误 泛型类 实例化 | 更新日期: 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类型的变量。如果TStringBuilder之类的呢?

从根本上说,你的ValidationHelper声称是通用的,但然后是特定于CustomerValidator,这似乎很奇怪。

如果不知道FluentValidation库,我们就不能真正知道CustomerValidator是做什么的——比如它实现了Validator<Customer>吗?我突然想到,您可能希望将验证器传递到Validate方法或ValidatorHelper构造函数中。(我强烈怀疑您想要摆脱的静态修饰符-如果方法是静态的,它就不能在基类中实现抽象方法…如果类是静态的,它甚至不能指定基类)

基本上,您需要考虑:

  • 关于CustomerValidator应该知道什么?可能不是是一个通用的助手类。
  • 应该如何创建验证器?选项:
    • helper本身(可能使用new()约束)
    • 创建helper实例的调用者,假设你要一个实例
    • 调用Validate方法

可能想要这样的东西:

// 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;
    }
}