简体   繁体   中英

Inheritance: Unable to access method from base class

I am implementing CQRS pattern. To use CQRS pattern in my project I wrote three commands, they are

public class DogCommand : PetCommand
{
    public DogCommand(){}
    public override string Name{get; set;}
}

public class CatCommand : PetCommand
{
    public CatCommand(){}
    public override string Name{get; set;}
}

public abstract class PetCommand : ICommand
{
    public PetCommand(){}
    public virtual string Name{get; set;}
}

public interface ICommand
{
   //Business logic
 }

Here I have interface called ICommand . PetCommand is base class which is implementing this interface. Derived class DogCommand and CatCommand are inheriting PetCommand .

I also wrote base command handler, as below

public abstract class BaseCommandHandler<T> : CommandHandler<T> where T : ICommand
{
    protected BaseCommandHandler(string type, string name): base(type, name)
    {

    }
}
public abstract class CommandHandler<T> : ICommandHandler<T> where T : ICommand
{
   protected CommandHandler(string type, string name)
   {
    //Business logic
   }

   protected void LogWrite(T command)
   {
      //Writing log 
   }
}


public interface ICommandHandler<in T> where T : ICommand
{
    void Run(T command);
}

All functions present in BaseCommandHandler , I will use in each derived command handler

Now problem is in derived class command handler

public class PetCommandHandler : BaseCommandHandler<DogCommand>, ICommandHandler<CatCommand> 
{

    public void Run(DogCommand dCommand)
    {
        this.LogWrite(dCommand)      
    }

    public void Run(CatCommand cCommand)
    {
       **//Want to access this.LogWrite() with cCommand. How can I do that?**          
    }
}

Here I am unable to access this.LogWrite() function for cCommand, because PetCommandHandler is inheriting first BaseCommandHandler and then implementing ICommandHandle.

How to access this.LogWrite() function for cCommand?

Here is compile time error:

cannot convert from 'Command.DogCommand' to 'Command.CatCommand'


Update :

First way to fix this issue :

I can fix this issue by using base command ie PetCommand in BaseCommandHandler instead of DogCommand . This will help me to access all derived classes in this.LogWrite() function, but this will lead me to implement empty Run(PetCommand petCommand) {} function, that I don't want to do.

Second way :

I can change LogWrite() function as virtual in CommandHandler and override whenever I face this situation.

I really appreciate if someone provide me any other solution for this issue.

You have a design issue to resolve.

You are trying to handle Two separate Types in the generic class. This is not a extensible design.

When there will be a new class inheriting from PetCommand created, you will have to change PetCommand handler class to implement interface ICommandHandler<newPetCommand> . That's basically a bad design.

The command handler class of yours should deal with the Pet, not with a specific type of Pet such as Cat or Dog.

You need to have CommandHandler and PetCommandHandler class as following.

public abstract class CommandHandler<T> : ICommandHandler<T> where T : ICommand
{
    protected CommandHandler(string type, string name)
    {
        //Business logic
    }

    //Making Run method abstract so that 
    //individual Handler class can have their own logic in it.
    public abstract void Run(T command);

    //Common implementation for LogWrite.
    //If this also requires override, it can be made virtual 
    //so that deriving class can override the logic.
    protected void LogWrite(T command)
    {
        //Writing log 
    }
}

//PetCommandHandler class now can be used for any class object 
//which is inheriting PetCommand class.
public class PetCommandHandler<T> : BaseCommandHandler<T> where T: PetCommand
{
    public PetCommandHandler(string type, string name) : base(type, name)
    {

    }

    public override void Run(T dCommand)
    {
        this.LogWrite(dCommand);
    }
}

How to test?

var dog = new DogCommand();
var commandHandler = new PetCommandHandler<DogCommand>("Dog", "Tom");
commandHandler.Run(dog);

var cat = new CatCommand();
var catHandler = new PetCommandHandler<CatCommand>("Cat", "Mini");
catHandler.Run(cat);

If you later introduce new PetCommand class, let say PandaCommand . You can still use PetHandler as following.

var pandaHandler = new PetHandler<PandaCommand>("Panda", "Po");
var panda = new PandaCommand();
pandaHandler.Run(panda);

If you do not want to create separate instance of PetCommandHandler for different PetCommand type. You can change the PetCommandHandler class as following.

public class PetCommandHandler : BaseCommandHandler<PetCommand>
{
    public PetCommandHandler(string type, string name) : base(type, name)
    {

    }
    public override void Run(PetCommand dCommand)
    {
        this.LogWrite(dCommand);
    }
}

With this class you just need to create only one instance of PetCommndHandler and you can execute Run method with any object of PetCommand

var patCommandHandler = new PetCommandHandler("someType", "someName");
patCommandHandler.Run(dog);
patCommandHandler.Run(cat);
patCommandHandler.Run(panda);

I hope this will help you resolve your issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM