继承:无法从基类访问方法

时间:2019-08-29 09:55:15

标签: c# inheritance design-patterns cqrs

我正在实现CQRS模式。为了在我的项目中使用CQRS模式,我编写了三个命令,它们是

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
 }

在这里,我有一个名为ICommand的界面。 PetCommand是实现此接口的基类。派生类DogCommandCatCommand继承了PetCommand

我还编写了基本的命令处理程序,如下所示

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

BaseCommandHandler中存在的所有函数,我将在每个派生的命令处理程序中使用

现在问题出在派生类命令处理程序中

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?**          
    }
}

这里我无法访问cCommand的this.LogWrite()函数,因为PetCommandHandler继承了 first BaseCommandHandler then 实现ICommandHandle

  

如何访问cCommand的this.LogWrite()功能?

这是编译时错误:

  

无法从“ Command.DogCommand”转换为“ Command.CatCommand”


更新:

解决此问题的第一种方法:

我可以通过使用基本命令(即PetCommand中的BaseCommandHandler而不是DogCommand来解决此问题。这将帮助我访问this.LogWrite()函数中的所有派生类,但这将导致我实现我不想执行的空Run(PetCommand petCommand) {}函数。

第二种方式:

每当遇到这种情况时,我都可以在LogWrite()virtual中将CommandHandler的功能更改为override

非常感谢有人为我提供其他解决方案。

1 个答案:

答案 0 :(得分:0)

您有要解决的设计问题。

您正在尝试处理泛型类中的两个单独的类型。这不是可扩展的设计。

当将创建一个从PetCommand继承的新类时,您将不得不更改PetCommand处理程序类以实现接口ICommandHandler<newPetCommand>。这基本上是一个糟糕的设计。

您的命令处理程序类应该处理Pet,而不要处理特定类型的Pet,例如Cat或Dog。

您需要具有CommandHandler和PetCommandHandler类,如下所示。

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

如何测试?

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

如果您稍后引入新的PetCommand类,请说PandaCommand。您仍然可以按照以下方式使用PetHandler。

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

如果您不想为不同的PetCommand类型创建PetCommandHandler的单独实例。您可以按以下方式更改PetCommandHandler类。

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

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

使用此类,您只需要创建PetCommndHandler的一个实例,就可以对PetCommand的任何对象执行Run方法

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

我希望这可以帮助您解决问题。