简体   繁体   English

通过回调或事件引发处理多种消息类型的设计模式

[英]Design pattern for handling multiple message types with callback or event raising

I read about Strategy pattern in this question. 我在这个问题中读到了战略模式。 I ran into a problem when wrapping all this in MessageProcessor, and cannot give the user of my class any strong typed callback. 将所有这些都包装在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
    }
}

I tried to explain my problem in code comments. 我试图在代码注释中解释我的问题。 Is it possible to give a user of my DLL any typed callback if I only provide a MessageProcessor class that determines a type of message and calls typed strategy class? 如果仅提供确定消息类型并调用类型化策略类的MessageProcessor类,是否可以为DLL用户提供任何类型化的回调? Or I should leave the user to write strategy determination code (in this case MessageProcessor)? 还是我应该让用户编写策略确定代码(在这种情况下为MessageProcessor)?

I know I can have event to call when processing is done, but that event would be in base MessageProcessing class, so it cannot have typed event arguments. 我知道处理完成后可以调用事件,但是该事件将在基本MessageProcessing类中进行,因此它不能具有类型化的事件参数。 EDIT I provided some more code, to help understand what I need. 编辑我提供了更多代码,以帮助了解我所需要的。

//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
    }
}

It is not strictly necessary to use an interface for the strategy pattern. 并非必须将接口用于策略模式。 You can declare an abstract class MessageProcessing and a method ProcessMessage which uses the template pattern. 您可以声明一个抽象类MessageProcessing和一个使用模板模式的ProcessMessage方法。 In his logic, the code executes internal processing method and then raises an event. 按照他的逻辑,代码执行内部处理方法,然后引发一个事件。

Something like this: 像这样:

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

As you can see, the ProcessMessage acts as a template. 如您所见,ProcessMessage充当模板。 This means that it has a logic flow (very simple, just two lines of code) in which first executes an abstract method. 这意味着它具有逻辑流程(非常简单,只有两行代码),其中首先执行抽象方法。 After that, it raise the event. 之后,它引发事件。

The abstract method must be implemented for each class that derives from this class. 必须为从该类派生的每个类实现抽象方法。 This method has the logic of your classes that implement your current interface. 此方法具有实现当前接口的类的逻辑。

With this, you only execute methods on the abstraction, and internally the event is raised. 这样,您仅在抽象上执行方法,并且在内部引发事件。

Is that what you need? 那是你需要的吗?

Greetings! 问候!

I ran into a problem when wrapping all this in MessageProcessor, and cannot give the user of my class any strong typed callback. 将所有这些都包装在MessageProcessor中时遇到了一个问题,并且无法为我的类用户提供任何强类型的回调。

The problem here is that MessageProcessor creates all MessageProcessing instances. 这里的问题是MessageProcessor创建所有MessageProcessing实例。

Or I should leave the user to write strategy determination code (in this case MessageProcessor)? 还是我应该让用户编写策略确定代码(在这种情况下为MessageProcessor)?

The solution is to write a MessageProcessor , that can be configured by the user by registering MessageProcessing instances. 解决方案是编写一个MessageProcessor ,用户可以通过注册MessageProcessing实例进行配置。

Is it possible to give a user of my DLL any typed callback if I only provide a MessageProcessor class that determines a type of message and calls typed strategy class? 如果仅提供确定消息类型并调用类型化策略类的MessageProcessor类,是否可以为DLL用户提供任何类型化的回调?

Configuration phase: 配置阶段:

  1. The user creates a MessageProcessor instance provided by the library 用户创建该库提供的MessageProcessor实例
  2. The user creates all necessary MessageProcessings , provided by the library or by the user, registers callbacks and subscribes to MessageProcessings events 用户创建由库或用户提供的所有必要的MessageProcessings ,注册回调并订阅MessageProcessings事件
  3. The user registers all created MessageProcessings in the MessageProcessor 用户在MessageProcessings中注册所有创建的MessageProcessor

Message processing phase: 消息处理阶段:

  1. The user calls the configured MessageProcessor to process a Message 用户调用已配置的MessageProcessor来处理Message
  2. The configured MessageProcessor looks though registered MessageProcessings for a MessageProcessing , capable of processing the Message 配置的MessageProcessor通过已注册的MessageProcessings查找一个能够处理MessageMessageProcessing
  3. The MessageProcessor passes the Message to the found MessageProcessing 所述MessageProcessor传递Message到所找到的MessageProcessing
  4. The MessageProcessing makes all necessary callbacks and raises events to interact with the user MessageProcessing进行所有必要的回调并引发事件以与用户交互

Hint: 暗示:

To check if MessageProcessing is capable of processing a Message add abstract bool CanProcess(Message) method to the base MessageProcessing class and override it in concrete MessageProcessing classes. 若要检查MessageProcessing是否能够处理Message ,请在基本MessageProcessing类中添加抽象bool CanProcess(Message)方法,并在具体的MessageProcessing类中重写它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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