EventBus 事件总线模式实例(发布/订阅事件)

       在我们公司经常用到总线,具体的总线是什么让我理解我也不清楚,但是在这几个月下来,我已经知道总线如何使用,现在加上示例讲解总线如何使用。

1. 首先我们的新建一个类,这个类其实是用于总线传递的模型

   

using System;

namespace PurchaseDevices.Model.CommonModel
{
/// <summary>
/// 事件传递参数
/// </summary>
/// <typeparam name="T"></typeparam>
public class FlowDataEventArgs<T> : EventArgs
{
public FlowDataEventArgs(T data)
{
Data = data;
}
public T Data { get; set; }
}
}

 

2. 建立一个类(FlowServiceBus),里面来写总线的方法。

  public class FlowServiceBus

{
   static FlowServiceBus _flowServiceBus;

public static FlowServiceBus Instance
{
get
{
if (_flowServiceBus == null) _flowServiceBus = new FlowServiceBus();
return _flowServiceBus;
}
}

}

 

4. 写一个方法,里面挂总线

  public class FlowServiceBus

{
   static FlowServiceBus _flowServiceBus;

public static FlowServiceBus Instance
{
get
{
if (_flowServiceBus == null) _flowServiceBus = new FlowServiceBus();
return _flowServiceBus;
}
}

 

 public void ConfigMsgDispachRule(){

   //挂总线

}

 

}

 

 

5. 先讲一讲我们传统的调用另一个类的方法

//新建一个对象模型类

public class FarmerCardOrRateSellModel
{
public FarmerCardOrRateSellModel()
{
PackageHead = 0xAA;
FixedLength = 11;
}

/// <summary>
/// 帧头
/// 帧开始标记,0xAA
/// </summary>
public byte PackageHead { get; set; }
/// <summary>
/// 接收者,标识数据要发给谁
/// 1磅码主机、2定级键盘、3交烟刷卡。
/// </summary>
public byte Receiver { get; set; }
/// <summary>
/// 发送者,标识数据是谁发出
/// 1磅码主机、2定级键盘、3交烟刷卡。
/// </summary>
public byte Sender { get; set; }
/// <summary>
/// Zigbee通信地址
/// 1~15
/// </summary>
public byte ZigbeeAddress { get; set; }
/// <summary>
/// 帧序号
/// 0~255
/// </summary>
public byte FrameNumber { get; set; }
/// <summary>
/// 命令码
/// </summary>
public byte Command { get; set; }
/// <summary>
/// 数据区字节数
///
/// </summary>
public int DataLength { get; set; }
/// <summary>
/// 数据区,可无(数据区为0)
/// </summary>
public byte[] Data { get; set; }
/// <summary>
/// 从receiver到整个data的和校验
/// </summary>
public byte Crc { get; set; }
/// <summary>
/// 定长 除开数据区的长度 定长为11
/// </summary>
public int FixedLength { get; set; }

}

 

//我们现在要做的是  根据不同的发送者Sender  ,进入不同的方法

private void DisSenderToDisWay(FarmerCardOrRateSellModel farmerCardOrRateSellModel)
{
DevTypeEnum devTypeEnum = (DevTypeEnum)farmerCardOrRateSellModel.Sender;  //这里是一个枚举,这里就不详细讲解了,这里就是说                                                                                                                                                           //Sender有不同的值
switch (devTypeEnum)
{

case DevTypeEnum.CardDev:
    CardDev cardDev=new CardDev ();

   cardDev.CardDevWay(farmerCardOrRateSellModel);

break;
case DevTypeEnum.LevelDev:

LevelDev levelDev=new LevelDev();

levelDev.LevelDevWay(farmerCardOrRateSellModel);

 

break;
default:
Logger.GetInstance().Warn("无法识别的发送者");
break;
}
}

 

//当sender为CardDev要执行的方法

public class  CardDev{

    public  void   CardDevWay(FarmerCardOrRateSellModel farmerCardOrRateSellModel){

//执行的方法

}

}

 

 

//当sender为LevelDev要执行的方法

public class  LevelDev{

    public  void   LevelDevWay(FarmerCardOrRateSellModel farmerCardOrRateSellModel){

//执行的方法

}

}

 

}

 

在传统的方法中 ,一个类要引用另一个类的方法,我们必须new 一个对象,然后引用方法。这样写没有错,我以前也是这样写的,对于一些不复杂程序中的我么可以这样写,但是在一些与设备交互的程序中,多半是总线将各个方法连接起来,我们不必关心谁是发送者,谁是接收者,每个方法只关心我拿到这个传递过来的值,该干什么,我也不必关心我应该把这个方法的结果发给谁用。这样低耦合。

  

 

   现在我们来讲讲用总线的方法,应该怎么写:

   还是保留FarmerCardOrRateSellModel类。

 

下面这个方法 我们用事件来写:

写事件:

public event EventHandler<FlowDataEventArgs<FarmerCardOrRateSellModel>> OnReceiveCardDataEventHadler;

  public event EventHandler<FlowDataEventArgs<FarmerCardOrRateSellModel>> OnReceiveLevelDataEventHadler;

 

private void DisSenderToDisWay(FarmerCardOrRateSellModel farmerCardOrRateSellModel)
{
DevTypeEnum devTypeEnum = (DevTypeEnum)farmerCardOrRateSellModel.Sender;  
switch (devTypeEnum)
{

case DevTypeEnum.CardDev:

if (OnReceiveCardDataEventHadler!=null)
{
OnReceiveCardDataEventHadler(this,new FlowDataEventArgs<FarmerCardOrRateSellModel>(farmerCardOrRateSellModel));
}

break;
case DevTypeEnum.LevelDev:

 

if (OnReceiveLevelDataEventHadler!=null)
{
OnReceiveLevelDataEventHadler(this, new FlowDataEventArgs<FarmerCardOrRateSellModel>(farmerCardOrRateSellModel));

}

break;
default:
Logger.GetInstance().Warn("无法识别的发送者");
break;
}
}

 

//我们要写两个方法  ,这两个方法就是Sender为LevelDev 和CardDev,他们拿到数据自己需要怎么处理的方法了

//当sender为CardDev要执行的方法

public class  CardDev{

    public  void   CardDevWay(object sender, FlowDataEventArgs<FarmerCardOrRateSellModel> e){

     var data=e.Data;  //data就为传送过来的FarmerCardOrRateSellModel对象

}

}  

//当sender为LevelDev 要执行的方法

public class  LevelDev{

    public  void   LevelDevWay(object sender, FlowDataEventArgs<FarmerCardOrRateSellModel> e){

    var data=e.Data;  //data就为传送过来的FarmerCardOrRateSellModel对象

}

}

 

//写到这里 我们已经把各自内部的方法完成了,现在我们要完成的就是 ,如何将方法与方法直接串联起来,怎么让sender为CardDev时就进入对应的CardDevWay方法南。那么现在就是要挂总线了。

 

还记的我们在总线类里面写的方法么:

现在我们要在里面添加一些代码了。

  public class FlowServiceBus

{
   static FlowServiceBus _flowServiceBus;

public static FlowServiceBus Instance
{
get
{
if (_flowServiceBus == null) _flowServiceBus = new FlowServiceBus();
return _flowServiceBus;
}
}

 

//新建对象

  private  readonly  DisSenderToDisWay  _disSenderToDisWay=new DisSenderToDisWay();

  private  readonly  CardDev _cardDev=new CardDev ();

  private  readonly  LevelDev _levelDev=new LevelDev ();

 public void ConfigMsgDispachRule(){

 

  EventBroker eventBroker =new EventBroker();

 

eventBroker.SpecialCasesRegistrar.AddPublication("发送者为CardDev 的方法", _disSenderToDisWay,
"OnReceiveCardDataEventHadler", HandlerRestriction.None);

eventBroker.SpecialCasesRegistrar.AddSubscription<FlowDataEventArgs<FarmerCardOrRateSellModel>>("发送者为CardDev 的方法",
_cardDev, _cardDev.CardDevWay, new OnPublisher());

//这是一组对应的  可以这样理解 :当执行到DisSenderToDisWay 类里面的OnReceiveCardDataEventHadler事件时,就执行CardDev 里面的CardDevWay方法

//按照以上的里面  当我们执行DisSenderToDisWay 类里面的OnReceiveLevelDataEventHadler事件时,接下来我们应该执行LevelDev类里面的LevelDevWay方法南

 

eventBroker.SpecialCasesRegistrar.AddPublication("发送者为LevelDev  的方法", _disSenderToDisWay,
"OnReceiveLevelDataEventHadler", HandlerRestriction.None);
eventBroker.SpecialCasesRegistrar.AddSubscription<FlowDataEventArgs<FarmerCardOrRateSellModel>>("发送者为LevelDev 的方法",
_levelDev, _levelDev.LevelDevWay, new OnPublisher());

}

}

总线这个要慢慢理解,刚开始我也不知道如何将两个方法挂接起来的,慢慢的理解就行了。在平常代码中我们很少使用总线,但是对于有些公司可能还是经常会用到的,对于那些刚刚接触到总线的朋友们,希望对你们初步理解与简单使用有帮助。

 

posted @ 2017-01-03 15:40  姚小丹  阅读(661)  评论(0编辑  收藏  举报