【问题标题】:Inheritance: Unable to access method from base class继承:无法从基类访问方法
【发布时间】:2019-08-29 09:55:15
【问题描述】:

我正在实施 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 BaseCommandHandlerthen 实现 ICommandHandle。

cCommand如何访问this.LogWrite()函数?

这是编译时错误:

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


更新:

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

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

第二种方式:

每当我遇到这种情况时,我都可以将 CommandHandleroverride 中的 virtual 功能更改为 virtual

如果有人为此问题提供任何其他解决方案,我真的很感激。

【问题讨论】:

  • PetCommandHandler 试图拥有两个宠物类型,为什么?
  • 嗯,这里没有显示LogWrite 的重载,它接受DogCommandCatCommand
  • 看起来您正在尝试“伪造”多重继承。我只需创建一个DogCommandHandler 和一个CatCommandHandler
  • @ChetanRanpariya,是的,因为PetCommandHandler 将支持所有PetCommands。我不能为从PetCommand 删除的每个命令编写单独的命令处理程序。
  • 是的,写PetCommandHandler 以获取PetCommand

标签: c# inheritance design-patterns cqrs


【解决方案1】:

您有一个设计问题需要解决。

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

当将创建一个继承自PetCommand 的新类时,您必须更改 PetCommand 处理程序类以实现接口ICommandHandler&lt;newPetCommand&gt;。这基本上是一个糟糕的设计。

您的命令处理程序类应该处理宠物,而不是特定类型的宠物,例如猫或狗。

你需要有如下的 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);

希望这能帮助您解决问题。

【讨论】:

  • 对于其余的命令,我使用的是您的最后一个选项。对于Pet,我有不同的实现。我将继续前进,并在我的大部分命令中遵循您的最后一个选项。对于DogCommandCatCommand(其中包含一些特殊功能),我将编写单独的命令处理程序,而不是在同一个CommandHandler 中执行。感谢您的时间和努力。我接受你的回答,涵盖了我的所有场景
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
  • 2012-11-15
  • 2013-09-27
  • 2013-09-09
相关资源
最近更新 更多