错误报告

本文关键字:报告 错误 | 更新日期: 2023-09-27 17:58:06

我有一个遵循命令模式的类。它有两个方法,分别是Execute和CanExecute,CanExecute检查是否调用Execute(它们源自ICommand)。CanExecute调用一些方法来检查所有必需的服务是否正在运行、版本是否正确等。

调用CanExecute后,它可能会失败并返回false,我需要知道原因。是因为版本不好、服务、文件丢失等原因吗?

了解问题的最佳策略是什么

一种选择是,每当所需条件失败时,我可以抛出一个异常,在消息字段中描述错误。然而,它失败的可能性是意料之中的,您不应该对常规的控制流使用异常。所以我真的不确定。

谢谢。

错误报告

您可以使用一组"原因",告诉类的用户为什么CanExecute返回false。原因可以是一个简单的CCD_ 2。

public bool CanExecute() {
  var messages = new List<string>();
  if (!Condition1) {
    messages.Add("Missing Condition1");
  }
  ...
  Messages = messages;
  return messages.Count == 0;
}
public IEnumerable<string> Messages { get; private set; }

然后,客户端代码可以向最终用户显示消息的集合。

更新

您还可以将新的命令与消息关联起来,为用户提供解决所发现问题的方法。在这种情况下,您可以创建自己的类来封装该信息,而不是IEnumerable<string>

public class Message {
  public string Text { get; set; }
  public ICommand Command { get; set; }
}
...
public bool CanExecute() {
  var messages = new List<Message>();
  if (!Condition1) {
    messages.Add(
      new Message { 
        Text = "Missing Condition1", 
        Command = new FixCondition1Command() 
      }
    );
  }
  ...
  Messages = messages;
  return messages.Count == 0;
}
public IEnumerable<Message> Messages { get; private set; }

更新:根据反馈返工

由于UI需要CanExecute()返回false的原因,所以会想到两件事:

选项1:将可枚举消息属性添加到命令接口,并在调用CanExecute()期间根据需要填充它。然后,UI可以根据需要询问该属性。如果采用这种方法,请确保每次调用CanExecute()时都清除属性的内容,这样就不会丢失对状态的跟踪。

public interface ICommand
{
    IEnumerable<string> Messages { get; }
    bool CanExecute();
    void Execute();
}
public class SomeCommand : ICommand
{
    public IEnumerable<string> Messages { get; private set; }
    public bool CanExecute()
    {
        var messages = new List<string>();
        var canExecute = true;
        if (SomeCondition)
        {
            canExecute = false;
            messages.Add("Some reason");
        }
        if (AnotherCondition)
        {
            canExecute = false;
            messages.Add("Another reason");
        }
        Messages = messages;
        return canExecute;
    }
    public void Execute() { }
}

选项2:让CanExecute()返回一个包含bool和可枚举消息属性的对象。这使得消息显然只适用于CanExecute()的调用。然而,根据您在哪里/如何实现(例如,数据绑定),这可能会使其他场景比您想要的更复杂。

public class CanExecuteResult
{
    public bool CanExecute { get; set; }
    public IEnumerable<string> Messages { get; set; }
}
public interface ICommand
{
    CanExecuteResult CanExecute();
    void Execute();
}
public class SomeCommand : ICommand
{
    public CanExecuteResult CanExecute()
    {
        var result = new CanExecuteResult { CanExecute = true };
        var messages = new List<string>();
        if (SomeCondition)
        {
            result.CanExecute = false;
            messages.Add("Some reason");
        }
        if (AnotherCondition)
        {
            result.CanExecute = false;
            messages.Add("Another reason");
        }
        result.Messages = messages;
        return result;
    }
    public void Execute() { }
}

显然,具体如何处理接口、可枚举类型等取决于您自己。代码只是这个想法的一个表示。

    Bool CanExecute()
    {
     if(!CheckXXX)
      throw new Exception("CheckXXX function throws an exception")
     if(!CheckYYY)
      throw new Exception("CheckYYY function throws an exception")
    if(!CheckZZZ)
     throw new Exception("CheckZZZ function throws an exception")
    return true; //everything is working fine    
}