首页 > 解决方案 > 如何将消息与其信息和实现脱钩?

问题描述

C#语言编写的场景,我的解决方案中的三个主要项目:Remote、Event和Model。

远程:管理来自远程系统的套接字。远程有两个处理程序:通知连接状态,从远程系统发送消息。

事件:围绕所有解决方案发布消息

模型:商业逻辑。

我希望 Remote 与系统的其余部分隔离,我的意思是在 Model 中构建一个管理器,它拦截来自 Remote 的通知并使用 Event 来传播消息。我希望模型中的所有其他管理人员只知道模型,而不知道消息的远程实现。

我已经制作了自定义消息以通过 Event 发布来自 Remote 的连接状态,我的问题如下:我如何在没有谁拦截消息知道实现的情况下发送消息?每条消息都有不同的属性。

我试图在模型中制作一个消息,它与远程消息的接口相同。

但是在这种情况下每个人都可以注册模式来获取消息,但必须知道消息获取属性的实现。

通过事件在模型周围发送的消息

MessageEvent: IEvent

public const string Name="MessageEvent"

// The message implemented in Remote
public IRemoteMessage RemoteMessage {get; private set;}

public void MessageEvent(IRemoteMessage rm)
{
    // I want to avoid make a copy of the original message, too much classes to have same information
    RemoteMessage = rm;
}

模型中 CommunicationManager 中的远程处理程序


RemoteService.ReceivedData += OnReceiveData;

OnReceiveData(object sender, DataArgs e)
{
    var remoteMessage = e as IRemoteMessage;
    EventService.Publish(new MessageEvent(remoteMessage))
}

每个人都可以将模型中的事件(观察者)注册为:

EventService.Register(OnManageData, MessageEvent.Name)

\\..

private void OnManageData(EvtData arg)
{   
    if (arg is MessageEvent)
    {
        var me = arg as MessageEvent;

        // I have the problem here, I can cast remoteMessage by its impementation in Remote to get the properties but I don't want it!!!
        var remoteMessage = me.RemoteMessage;
    }
}

一切都在我的真实场景中有效,但我重复我自己:

  1. 远程没有引用模型或事件
  2. Model 必须通过 CommunicationManager 将消息从 Remote 传播到 Model 中的所有其他管理器
  3. 没有人知道远程消息的实现

每一个建议将不胜感激

标签: c#design-patternsdecoupling

解决方案


我推荐使用“桥梁设计模式”。Bridge 是一种结构设计模式,将业务逻辑或巨大的类划分为可以独立开发的独立类层次结构。

这里是一个使用多个输入参数发送多种类型消息的示例:

/// <summary>
/// The 'Abstraction' class
/// </summary>
public abstract class Message
{
 public IMessageSender MessageSender { get; set; }
 public string Subject { get; set; }
 public string Body { get; set; }
 public abstract void Send();
}

/// <summary>
/// The 'RefinedAbstraction' class
/// </summary>
public class SystemMessage : Message
{
 public override void Send()
 {
 MessageSender.SendMessage(Subject, Body);
 }
}

/// <summary>
/// The 'RefinedAbstraction' class
/// </summary>
public class UserMessage : Message
{
 public string UserComments { get; set; }

 public override void Send()
 {
 string fullBody = string.Format("{0}\nUser Comments: {1}", Body, UserComments);
 MessageSender.SendMessage(Subject, fullBody);
 }
}

/// <summary>
/// The 'Bridge/Implementor' interface
/// </summary>
public interface IMessageSender
{
 void SendMessage(string subject, string body);
}

/// <summary>
/// The 'ConcreteImplementor' class
/// </summary>
public class EmailSender : IMessageSender
{
 public void SendMessage(string subject, string body)
 {
 Console.WriteLine("Email\n{0}\n{1}\n", subject, body);
 }
}

/// <summary>
/// The 'ConcreteImplementor' class
/// </summary>
public class MSMQSender : IMessageSender
{
 public void SendMessage(string subject, string body)
 {
 Console.WriteLine("MSMQ\n{0}\n{1}\n", subject, body);
 }
}

/// <summary>
/// The 'ConcreteImplementor' class
/// </summary>
public class WebServiceSender : IMessageSender
{
 public void SendMessage(string subject, string body)
 {
 Console.WriteLine("Web Service\n{0}\n{1}\n", subject, body);
 }
}

/// <summary>
/// Bridge Design Pattern Demo
/// </summary>
class Program
{
 static void Main(string[] args)
 {
 IMessageSender email = new EmailSender();
 IMessageSender queue = new MSMQSender();
 IMessageSender web = new WebServiceSender();

 Message message = new SystemMessage();
 message.Subject = "Test Message";
 message.Body = "Hi, This is a Test Message";

 message.MessageSender = email;
 message.Send();

 message.MessageSender = queue;
 message.Send();

 message.MessageSender = web;
 message.Send();

 UserMessage usermsg = new UserMessage();
 usermsg.Subject = "Test Message";
 usermsg.Body = "Hi, This is a Test Message";
 usermsg.UserComments = "I hope you are well";

 usermsg.MessageSender = email;
 usermsg.Send();

 Console.ReadKey();
 }
}

有关更多信息,请参阅以下链接:

桥梁设计模式


推荐阅读