工厂来创建泛型类

本文关键字:泛型类 创建 工厂 | 更新日期: 2023-09-27 18:27:10

我有一个名为Validator:的抽象类

public abstract class Validator<T> where T : IValidatable
{
    public abstract bool Validate(T input);
}

我有一些具体的实现。一个是AccountValidator:

public class AccountCreateValidator : Validator<IAccount>
{
    public override bool Validate(IAccount input)
    {
        //some validation
    }
}

另一个是LoginValidator:

public class LoginValidator : Validator<IAccount>
{
    public override bool Validate(IAccount input)
    {
        //some different validation
    }
}

我现在想创建一个工厂来返回验证器实现的一个实例。类似于:

public static class ValidatorFactory
{
    public static Validator GetValidator(ValidationType validationType)
    {
        switch (validationType)
        {
            case ValidationType.AccountCreate:
                return new AccountCreateValidator();
        }
    }
}

我想把它叫做

Validator myValidator = ValidatorFactory.GetValidator(ValidationType.AccountCreate); 

然而,它不喜欢返回新的AccountCreateValidator()行,也不喜欢我将myValidator声明为Validator而不是Validator<SomeType>。如有任何帮助,我们将不胜感激。

工厂来创建泛型类

您似乎正在使用工厂将枚举参数转换为具体的验证实现。但我可以想象,尽管调用者不知道或不关心验证器的具体类型,但它可能知道它希望验证的类型。这意味着将GetValidator方法作为一种通用方法是合理的:

public static Validator<TypeToValidate> GetValidator<TypeToValidate>(ValidationType validationType) where TypeToValidate : IValidatable

然后调用代码如下所示:Validator<IAccount> validator = ValidatorFactory.GetValidator<IAccount>(ValidationType.AccountCreate

如果你想像你所说的那样使用它,而不指定泛型参数,那么你可以声明一个非泛型接口,并让Validator抽象类实现它。未经测试,但大致如下:

public interface IValidator 
{
    bool Validate(object input);
}
public abstract class Validator<T> : IValidator where T : IValidatable
{
    public abstract bool Validate(T input);
    public bool Validate (object input)
    {
        return Validate ((T) input);
    }
}
public static class ValidatorFactory
{
    public static IValidator GetValidator(ValidationType validationType)
    {
        switch (validationType)
        {
            case ValidationType.AccountCreate:
                return new AccountCreateValidator();
        }
    }
}

然后这个代码:

IValidator myValidator = ValidatorFactory.GetValidator(ValidationType.AccountCreate); 

应该工作正常。

通常我会有一个接受Type作为参数的工厂,这样工厂就会创建一个唯一的派生类型。但是,因为您有多个验证器,它们接受相同类型的对象进行验证(在本例中为IAccount),我认为您必须向工厂提供通用参数,以及创建什么类型的验证器,如下所示:

public static class ValidatorFactory
{
    public static Validator<T> GetValidator<T>(ValidationType validationType) 
        where T : IValidatable
    {
        switch (validationType)
        {
            case ValidationType.AccountCreate:
                return new AccountCreateValidator() as Validator<T>;
                    // etc...
        }
    }
}

我试过打电话:

var value = ValidatorFactory.GetValidator<IAccount>(ValidationType.AccountCreate)

并且这现在将CCD_ 5转换为正确的CCD_。

这并不理想,因为您现在需要知道您想要什么验证器以及它接受什么输入,但如果由于我添加了显式强制转换(例如ValidatorFactory.GetValidator<IUser>(ValidationType.AccountCreate)应该失败)而传递了错误的输入类型,那么您应该会收到编译错误。

EDIT:因为有评论说这不会编译,所以我编辑了上面的代码片段,将其转换为new AccountCreateValidator() as Validator<T>。我以为它可以选任何一种方式,但显然不是(但不确定为什么)。我已经在LINQPad中验证了这一点,我可以从验证器中得到结果。

我还相信,我之前关于如果传入错误的泛型类型,可能会出现编译错误的评论不再适用于使用as关键字进行强制转换,如果无法执行,则只会返回null