mardi 26 janvier 2021

How to create a factory to create derived object accepting arguments of more derived type [duplicate]

I have a problem with designing a proper solution for a factory for a family of common-based classes. I have a class called Verifier, the class will have only method Verify which accepts instance of Specification as a parameter

public abstract class Verifier 
{
    public virtual bool Verify(Specification spec) 
    {
        //does the common job
        return true; //or false
    }
}

Then I have a set of concrete Verifiers

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

Then I have a nice factory which returns me a proper instance:

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();
        } 
    }
}

Now I have a requirement that the Verifiers can Verify not the instances of Specification but derived types of Specification, like:

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

This obviously will not compile, and I don't want to do tricks like this:

public abstract class FirstVerifier : Verifier
{
    public override bool Verify(Specification spec)
    {
       var realSpecification = spec as SpecificationOne;
       if(realSpecification == null)
          throw new Exception();
       // do job
    }
}

I am thinking of a solution (maybe a generic one) in which my factory returns proper type which in turn accepts proper type in Verify method, so that then I can use my factory to create verifiers and call verify, like this:

specifications.Select(s => VerifierFactory.Create(typeof(s)).Verify(s))

Aucun commentaire:

Enregistrer un commentaire