Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何创建工厂以创建接受更多派生类型参数的派生对象_C#_Generics_Design Patterns_Factory - Fatal编程技术网

C# 如何创建工厂以创建接受更多派生类型参数的派生对象

C# 如何创建工厂以创建接受更多派生类型参数的派生对象,c#,generics,design-patterns,factory,C#,Generics,Design Patterns,Factory,我在为一系列基于公共类的工厂设计合适的解决方案时遇到了问题。我有一个名为Verifier的类,该类只有一个方法Verifier,它接受规范实例作为参数 public abstract class Verifier { public virtual bool Verify(Specification spec) { //does the common job return true; //or false } } 然后我有一套具体的验证

我在为一系列基于公共类的工厂设计合适的解决方案时遇到了问题。我有一个名为Verifier的类,该类只有一个方法Verifier,它接受规范实例作为参数

public abstract class Verifier 
{
    public virtual bool Verify(Specification spec) 
    {
        //does the common job
        return true; //or false
    }
}
然后我有一套具体的验证器

public abstract class FirstVerifier : Verifier
{
    public override bool Verify(Specification spec) 
    {
       //does the job, maybe even calls for base or maybe not
       return true; 
    }
}

public abstract class SecondVerifier : Verifier
{
    public override bool Verify(Specification spec) 
    {
       //does the job, maybe even calls for base or maybe not
       return true; 
    }
}
然后我有一个很好的工厂,它返回给我一个合适的实例:

public class VerifierFactory 
{
    public static Verifier Create(string type) //not actually a string, but does not matter
    {
        switch (type) 
        {
            case "First": return new FirstVerifier();
            case "Second": return new SecondVerifier();
            default: throw new Exception();
        } 
    }
}
现在我有一个要求,验证者不能验证规范的实例,而是验证规范的派生类型,如:

public abstract class FirstVerifier : Verifier
{
    public override bool Verify(SpecificationOne spec)  //SpecificationOne derives from Specification
    {
       //does the job, maybe even calls for base or maybe not
       return true; 
    }
}

public abstract class SecondVerifier : Verifier
{
    public override bool Verify(SpecificationTwo spec) //SpecificationOne derives from Specification
    {
       //does the job, maybe even calls for base or maybe not
       return true; 
    }
}
这显然不会编译,我不想做这样的把戏:

public abstract class FirstVerifier : Verifier
{
    public override bool Verify(Specification spec)
    {
       var realSpecification = spec as SpecificationOne;
       if(realSpecification == null)
          throw new Exception();
       // do job
    }
}
specifications.Select(s => VerifierFactory.Create(typeof(s)).Verify(s))
我正在考虑一种解决方案,可能是一种通用的解决方案,其中我的工厂返回正确的类型,然后在Verify方法中接受正确的类型,这样我就可以使用我的工厂创建验证器并调用Verify,如下所示:

public abstract class FirstVerifier : Verifier
{
    public override bool Verify(Specification spec)
    {
       var realSpecification = spec as SpecificationOne;
       if(realSpecification == null)
          throw new Exception();
       // do job
    }
}
specifications.Select(s => VerifierFactory.Create(typeof(s)).Verify(s))

我想你可以用一般的方法。例如:

public abstract class Verifier 
{
    public virtual bool Verify<T>(T  spec) where T: Specification
    {
        //does the common job
        return true; //or false
    }
}
public class FirstVerifier : Verifier<SpecificationOne>
{
    public override bool Verify(SpecificationOne spec)
    {
        var baseResult = base.Verify(spec);

        //some logic

        return baseResult;
    }
}

public class SecondVerifier : Verifier<SpecificationTwo>
{
    public override bool Verify(SpecificationTwo spec)
    {
        var baseResult = base.Verify(spec);

        //some logic

        return baseResult;
    }
}
并从基本规范类继承其他规范

创建基本验证器类后,确认它是泛型类

public abstract class Verifier<T> where T : Specification
{
    public virtual bool Verify(T spec)
    {
        //does the common job
        return true; //or false
    }
}
您可以创建VerifierFactory,如下所示:

public class VerifierFactory
{
    public static Verifier<T> Create<T>(T spec) where T : Specification
    {
        if (spec.GetType() == typeof(SpecificationOne))
            return new FirstVerifier() as Verifier<T>;

        if (spec.GetType() == typeof(SpecificationTwo))
            return new SecondVerifier() as Verifier<T>;

        //and etc...
        // I think you project must have one default Verifier class for else case
    }
}
specifications.Select(s => VerifierFactory.Create(s).Verify(s))

我想你可以用一般的方法。例如:

public abstract class Verifier 
{
    public virtual bool Verify<T>(T  spec) where T: Specification
    {
        //does the common job
        return true; //or false
    }
}
public class FirstVerifier : Verifier<SpecificationOne>
{
    public override bool Verify(SpecificationOne spec)
    {
        var baseResult = base.Verify(spec);

        //some logic

        return baseResult;
    }
}

public class SecondVerifier : Verifier<SpecificationTwo>
{
    public override bool Verify(SpecificationTwo spec)
    {
        var baseResult = base.Verify(spec);

        //some logic

        return baseResult;
    }
}
并从基本规范类继承其他规范

创建基本验证器类后,确认它是泛型类

public abstract class Verifier<T> where T : Specification
{
    public virtual bool Verify(T spec)
    {
        //does the common job
        return true; //or false
    }
}
您可以创建VerifierFactory,如下所示:

public class VerifierFactory
{
    public static Verifier<T> Create<T>(T spec) where T : Specification
    {
        if (spec.GetType() == typeof(SpecificationOne))
            return new FirstVerifier() as Verifier<T>;

        if (spec.GetType() == typeof(SpecificationTwo))
            return new SecondVerifier() as Verifier<T>;

        //and etc...
        // I think you project must have one default Verifier class for else case
    }
}
specifications.Select(s => VerifierFactory.Create(s).Verify(s))

考虑一下这个解决方案。从一个通用的基本验证器开始,它提供一个验证规范部分的默认实现,然后调用子类的实现来验证T部分

您的选择必须更改为

specifications.Select(s => VerifierFactory.Create(s.GetType()).Verify(s))
此解决方案的优点是在每种情况下应用相同的验证模式,并避免在子类中强制转换,尽管在基类中确实有强制转换

然而,这种解决方案的缺点在于FirstVerifier可能会在VerifySpecification中接受错误的规范子类。要解决此问题,可以将基本验证器更改为

public abstract class Verifier<T> where T : Specification 
{
    public virtual bool Verify(T spec) 
    {
        if (!VerifyCommon(spec)) return false;
        return VerifyImplementation(spec);
    }

    protected abstract bool VerifyImplementation(T spec);

    protected bool VerifyCommon(Specification spec)
    {
        //does the common job
        return true; //or false
    }
}
此实现消除了内部验证的强制转换并确保了类型安全,但动态调用验证方法的成本可能可以忽略不计

这两种实现的优点在于

避免调用base.Verify,当子类的开发人员忘记调用该base.Verify时,它有时会导致错误。 可以在异构规范列表上操作。
考虑一下这个解决方案。从一个通用的基本验证器开始,它提供一个验证规范部分的默认实现,然后调用子类的实现来验证T部分

您的选择必须更改为

specifications.Select(s => VerifierFactory.Create(s.GetType()).Verify(s))
此解决方案的优点是在每种情况下应用相同的验证模式,并避免在子类中强制转换,尽管在基类中确实有强制转换

然而,这种解决方案的缺点在于FirstVerifier可能会在VerifySpecification中接受错误的规范子类。要解决此问题,可以将基本验证器更改为

public abstract class Verifier<T> where T : Specification 
{
    public virtual bool Verify(T spec) 
    {
        if (!VerifyCommon(spec)) return false;
        return VerifyImplementation(spec);
    }

    protected abstract bool VerifyImplementation(T spec);

    protected bool VerifyCommon(Specification spec)
    {
        //does the common job
        return true; //or false
    }
}
此实现消除了内部验证的强制转换并确保了类型安全,但动态调用验证方法的成本可能可以忽略不计

这两种实现的优点在于

避免调用base.Verify,当子类的开发人员忘记调用该base.Verify时,它有时会导致错误。 可以在异构规范列表上操作。
为什么不将参数类型更改为T,并在其中添加T:Specification?@gunr2171您是对的,我将编辑我的回答实际上,另一个选项是将的定义移动到类而不是方法。OP可以,这是一个可能的选项,尽管在T:Specification处执行公共抽象类验证是一个设计决策。这样,您就可以拥有一个公共类FirstVerifier:Verifier,并将泛型参数线程连接到Verify方法。@vanpersil我在我的回答中添加了VerifierFactory示例为什么不将参数类型更改为T,并在其中添加T:Specification?@gunr2171您是对的,我将编辑我的回答实际上,另一个选择是将的定义移到类而不是方法中。OP可以,这是一个可能的选择,尽管设计决定使用公共抽象类验证器,其中T:Specification。这样,您就可以拥有一个公共类FirstVerifier:Verifier,并将泛型参数线程连接到Verify方法。@vanpersil我在我的回答中添加了VerifierFactory示例语言不允许您尝试执行的操作有很好的理由。请参阅副本。根据您的具体情况,有一些备选方案可能有效,但您需要研究这些备选方案,确定哪些方案实际上是合适的,尝试应用这些方案,并仅在您有一些具体困难需要帮助时发布问题。链接的问题无法回答我的问题,因为我
合法地说,我不想检查参数是否是类的特定子类型。链接的问题甚至没有提到工厂问题,这是我想解决的主要困难。你问题的工厂方面根本不会影响答案。这是不必要的干扰。至于是否要检查参数类型,这很好,但它也不会改变语言中的合法性。副本是对你帖子中唯一一个非开放式问题的直接回答。问题的开放部分不适合或不适合堆栈溢出。有充分的理由表明该语言不允许您尝试执行的操作。请参阅副本。根据您的具体情况,有一些替代方案可能有效,但您需要研究这些替代方案,确定哪些(如果有的话)实际上是合适的,并尝试应用它们,只有当你有一些特定的困难需要帮助时,才发布一个问题。链接的问题不能回答我的问题,因为我明确地说我不想检查参数是否是类的特定子类型。链接的问题甚至没有提到工厂问题,这是我想解决的主要困难。你问题的工厂方面根本不会影响答案。这是不必要的干扰。至于是否要检查参数类型,这很好,但它也不会改变语言中的合法性。副本是对你帖子中唯一一个非开放式问题的直接回答。问题的开放部分不适合或不适合堆栈溢出。