【问题标题】:Design pattern for handling multiple message types with callback or event raising使用回调或事件引发处理多种消息类型的设计模式
【发布时间】:2015-06-01 13:22:15
【问题描述】:

我在this 问题中了解了策略模式。我在将所有这些包装在 MessageProcessor 中时遇到了问题,并且无法为我的类的用户提供任何强类型回调。

public class MessageProcessor
{
    private IMessageProcessing Processing {get; set;} // a processing strategy

    public void ProcessMessage(HubMessage message) //SignalR data message
    {
        ContentBase content = MessageProcessingBase.GetMessageContent(message); //just get content object from message

        if (content is DocumentFile) //this content holds info about file to download
               Processing = new DocumentFileProcessing();//implementation of IMessageProcessing strategy interface

        Processing.ProcessMessage(message); //here a file is being downloaded and I want to raise event or call a callback method to inform a client (this class's caller) about a path of downloaded file
    }
}

我试图在代码 cmets 中解释我的问题。如果我只提供一个确定消息类型并调用类型化策略类的 MessageProcessor 类,是否可以为我的 DLL 的用户提供任何类型化的回调?或者我应该让用户编写策略确定代码(在本例中为 MessageProcessor)?

我知道我可以在处理完成时调用事件,但该事件将在基本 MessageProcessing 类中,因此它不能具有类型化的事件参数。 编辑我提供了更多代码,以帮助了解我需要什么。

//lib code
public class Message
{
    public string From { get; set; }
    public string To { get; set; }
    public MessageContentBase Conent{get;set;}
}
public class MessageContentBase
{
    public string Note{get; set;}
}
public class DocumentFile: MessageContentBase
{
    public string FilePath { get; set; }
}
public abstract class MessageProcessing
{
    public abstract void ProcessMessage(Message message);
}
public class DocumentFileMessageProcessing:MessageProcessing
{
    public override void ProcessMessage(Message message)
    {
        DocumentFile df = message.Conent as DocumentFile;
        //1. download file
        //2. raise event or do callback in client code with parameter df.FilePath
    }
}
public class SomeOtherProcessing : MessageProcessing
{
    public override void ProcessMessage(Message message)
    {
        MessageContentBase content = message.Conent;
        //log.WriteLine("Message was from " + message.From);
    }
}
public class MessageProcessor
{
    MessageProcessing processing;
    public void ProcessMessage(Message message)
    {
        if (message.Conent is DocumentFile)
            processing = new DocumentFileMessageProcessing();
        //else if, else if.....
        processing.ProcessMessage(message);
    }
}
// end lib code

public class Program //client code
{
    public static void Main(string[] args)
    {
        Message m = new Message();
        MessageProcessor mp = new MessageProcessor();
        mp.ProcessMessage(m);
        // need something to call return-result-type-dependent post processing code
    }
}

【问题讨论】:

  • 那么你需要让你的用户通过你的消息处理器吗?
  • 这个类的调用者提供了IMessageProcessing策略?这样他就可以在那里回调。
  • 我想制作这样的系统: 我的 DLL 库:接收消息,处理消息,将处理后的数据传递给库用户。然后库用户继续处理特定消息处理结果的特定数据。不,我想让 MessageProcessor 确定它应该使用哪个 IMessageProcessing 实现。

标签: c# strategy-pattern


【解决方案1】:

对策略模式使用接口并不是绝对必要的。您可以声明一个抽象类 MessageProcessing 和一个使用模板模式的方法 ProcessMessage。在他的逻辑中,代码执行内部处理方法,然后引发事件。

类似这样的:

internal abstract class MessageProcessing {
  // TODO: declare event variable
  abstract string ProcessInternalMessage(HubMessage message);

  void ProcessMessage(HubMessage message) {
    // Here he call the ProcessInternalMessage which returns
    // the path. Depending on the derived class the logic or the processor.
    string path = this.ProcessInternalMessage(message);
    // here we raise event with the path in the parameters
  }
}

如您所见,ProcessMessage 充当模板。这意味着它有一个逻辑流程(非常简单,只有两行代码),其中首先执行一个抽象方法。之后,它引发事件。

必须为派生自此类的每个类实现抽象方法。此方法具有实现当前接口的类的逻辑。

这样,您只需执行抽象上的方法,并在内部引发事件。

这是你需要的吗?

您好!

【讨论】:

  • 这可能是我需要的,但我看到 ProcessInternalMessage 的返回类型是字符串。如果另一个处理返回一些复杂的数据怎么办?
  • 将返回类型从 String 更改为 object。然后,在模板中,引发事件并在 Event 类中发送执行类的类型 (this.GetType()) 以及对象。在客户端,由于返回可能会有所不同,因此您需要根据类型执行器来解释返回的对象。如果不是所有类都需要该事件,请从模板中删除该事件并在每个需要的类上实现它。
  • 是的,到目前为止,我没有看到任何更好的解决方案,只能让客户端编写 if-else 来检查返回类型。也许有更好的设计模式呢?我必须尽可能地编写更好的 DLL,这样客户就可以做很少的工作——这是我的意图。
  • 据我了解您的问题,更好的解决方案是引发不同类型的 EventArgs,每个派生类一个。在客户端,您只需声明处理程序,每个 EventArg 一个。在这种情况下,您可以避免 if else,通过事件应用控制反转。不幸的是,您没有太多其他选择,因为尽管您的代码具有共同的逻辑,但返回的对象是不同的,您需要使用它。我会选择 eventargs 选项。
【解决方案2】:

我在将所有这些包装在 MessageProcessor 中时遇到了问题,并且无法为我的类的用户提供任何强类型回调。

这里的问题是MessageProcessor 创建了所有MessageProcessing 实例。

或者我应该让用户编写策略确定代码(在本例中为 MessageProcessor)?

解决办法是写一个MessageProcessor,用户可以通过注册MessageProcessing实例来配置。

如果我只提供一个确定消息类型并调用类型化策略类的 MessageProcessor 类,是否可以为我的 DLL 的用户提供任何类型化的回调?

配置阶段:

  1. 用户创建库提供的MessageProcessor实例
  2. 用户创建库或用户提供的所有必要的MessageProcessings,注册回调并订阅MessageProcessings事件
  3. 用户在MessageProcessor中注册所有创建的MessageProcessings

消息处理阶段:

  1. 用户调用配置的MessageProcessor处理Message
  2. 配置的MessageProcessor看起来虽然注册MessageProcessingsMessageProcessing,能够处理Message
  3. MessageProcessorMessage 传递给找到的MessageProcessing
  4. MessageProcessing 进行所有必要的回调并引发事件以与用户交互

提示:

要检查MessageProcessing 是否能够处理Message,请将抽象bool CanProcess(Message) 方法添加到基类MessageProcessing 并在具体MessageProcessing 类中覆盖它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多