365投注平台总线知多少(1) – 「圣杰」

源码大大地:Github-EventBus
365投注平台公路知少量(1)
365投注平台公路知少量(2)

1. 小引

365投注平台公路大约地理念对你来说可能性很冷淡地,只提到遵守者(发行物订阅)时尚。,你可能性对此很熟识。。365投注平台公路是对发行物-订阅时尚的一种实现。它是一种集中式365投注平台处置机制,容许明显的的立法机构当中停止彼此传达指示方向显微镜凝块计数用不着相互信任,遂愿解耦的挥向。

咱们来看一眼365投注平台公路的处置工艺追逐:

图1:EventBus工艺追逐

知识了365投注平台公路的基本理念和处置工艺追逐,下面咱们就来辨析下办法去实现365投注平台公路。

2。回归自然

在入手实现365投注平台公路先发制人,咱们依然必要追踪源头。,探究一下365投注平台的实质和发行物订阅时尚的实现机制。

.365投注平台的实质

咱们先来讨论一下365投注平台的理念。他们都想出。,咱们都理应把事记住叙事的六岁基本信条。:时期、得第二名、字母、365投注平台(经、由于、成果)。

咱们以表达为例。,让我解说一下。。
用户输出用户名、邮筒、密电码后,点击加入,在心不在焉失常的反省经过。,加入成,邮务员发送用户。,必需品用户检验邮筒的致敏。。

嗨面就关涉了两个次要365投注平台:

  1. 加入365投注平台:记述是用户点击加入电钮。,反省输出。,成果是加入条件成。。
  2. 发送邮务员365投注平台:记述是用户在应用邮筒时必要检验邮筒。,邮务员发送后。,成果是邮务员条件成发送。。

真正这六基本信条也遵从的咱们顺序中365投注平台的处置追逐。任何独一使用Win整队顺序的人都了解。,当咱们设计UI时,,从衣物和装备中拖拽加入电钮(BTNEnter),双点取它,VS自发地为咱们增大下面的编码。:

void btnRegister_Click(OBJ)ect sender, EventArgs e)
{
 // 365投注平台的处置
}

到站的object sender首语重复法收回365投注平台的反对,这亦电钮反对。;EventArgs e 365投注平台参量,可以逮捕为对365投注平台的描画 ,它们可以统称为365投注平台源。到站的的编码逻辑,执意对365投注平台的处置。咱们可以把它统称为365投注平台处置

说得这么多了。,这一切都是经过气象布告实质。:365投注平台是由365投注平台源和365投注平台处置结婚

. 发行物订阅时尚

下定义反对当正中鹄的一对多信任相干,庶几乎究竟什么时辰反对翻转财产时,则占有信任于它的反对首府记下预示并被自发地花样翻新。 发行物订阅时尚

发行物/订阅时尚中有两个次要角色。:

  • 出版社(出版社):也被误认为是遵守者。,财产更改时预示占有订阅服务。。
  • 用户(用户):也被误认为是检查员。,订阅365投注平台并桥礅收到的365投注平台停止处置。

发行物/订阅时尚有两种实现办法。:

  • 简略实现办法:经过发行物服务技术维护订阅服务列表,当财产翻转时,成圈遍历列表被预示给订阅者。。
  • 付托实现:由Publisher下定义365投注平台付托,用户实现付托。

总而言之,发行物订阅时尚中有两个关键词。,预示与花样翻新。
预示遵守者花样翻新遵守者的财产。。
receiver 收音机是预示宁静反对在O时停止相关联的的更改。。

免得画一幅图片来表现大约地追逐的拔出,图形理应是大约的。:

图2:发行物订阅时尚工艺追逐

3 发行物订阅时尚的实现

信任下面的解说。,对365投注平台和发行物订阅时尚受胎独一大约的影象。大人物说学说理应与业务相结婚。,因而咱们不然移入手指来较好的地卡答卡答的故障声音编码。。
我将以遵守者时尚吸为例。,更普通的发行物订阅时尚可以经过重构来改良。。
首向上码:

/// 
/// 加夹箍夹牢类挥向计数
/// 
public enum FishType
{
    鲫鱼,
    吹毛求疵,
    黑鲸,
    青鱼,
    草鲤,
    鲈鱼
}

吸鱼竿的实现:

 /// 
 ///     钓鱼竿(评述)
 /// 
 public class FishingRod
 {
     public delegate void FishingHandler(FishType 典型) 宣言布置
     public event FishingHandler FishingEvent; //公告365投注平台

     public void ThrowHook(渔人 人)
     {
         (启动下独一钩子)!");

         随机数位仿照鱼骨,免得随机数位是偶数,鱼咬伤
         if (新的 作任意排列(下) % 2 == 0)
         {
             var type = (FishType) new 作任意排列()(下一步(0), 5);
             (贝尔):叮叮叮,鱼咬人。
             if (FishingEvent != 空)
                 FishingEvent(典型)
         }
     }
 }

吸者:

/// 
///     Angler(评述家)
/// 
public class 渔人
{
    public 渔人(string 姓名)
    {
        Name = name;
    }

    public string Name { get; set; }
    public int FishCount { get; set; }

    /// 
    /// 渔民必需有鱼竿。
    /// 
    public FishingRod FishingRod { get; set; }

    public void Fishing()
    {
        (大约地)
    }

    public void Update(FishType 典型)
    {
        FishCount++;
        ("{0}:使受限度局限A[ { 2 },{ 1 }鱼早已被使受限度局限。!", Name, FishCount, 典型)
    }
}

观察类亦充分简略的。:

//1、鱼竿设定初值
var fishingRod = new FishingRod();

//2、颁布发表吸者
var jeff = new 渔人("圣杰");

三。渔竿散布
Rod = fishingRod;

//4、加入遵守者
fishingRod.FishingEvent += jeff.Update;

//5、成圈接住
while (jeff.FishCount < 5)
{
    ();
    ("-------------------");
    //睡眠5s
    Thread.Sleep(5000);
}

编码很简略。,我信任你一眼就能读书。。但很明显,此编码实现仅遵从的CU。,免得常宁静观察,我也想应用大约地时尚。,咱们还必要重行下定义付托。,重行下定义365投注平台处置,它缺点很累吗?。契合不 repeat 你本身的信条,咱们必要重现它。。

结婚咱们对365投注平台实质的讨论,365投注平台是由365投注平台源和365投注平台处置结婚。为了咱们下面的证明某事属实的证据,public delegate void FishingHandler(FishType 典型)这句编码就早已阐明了365投注平台源和365投注平台处置。365投注平台源执意FishType type,365投注平台处置自然是加入到FishingHandler前述的代表的诉讼。
成绩早已处理了。,很显然是咱们的365投注平台源和365投注平台处置不敷抽象派的,因而它不能相信的性是遍及的。,如今让咱们来做点什么。。

. 使滴下365投注平台源

365投注平台源理应无论如何包住365投注平台发作的时期和突然发出或出现365投注平台的反对。
咱们使滴下IEventData啮合来封装365投注平台源:

/// 
/// 下定义365投注平台源啮合,占大约365投注平台源都要实现该啮合
/// 
public interface IEventData
{
    /// 
    /// 365投注平台发作的时期
    /// 
    DateTime EventTime { get; set; }

    /// 
    /// 突然发出或出现365投注平台的反对
    /// 
    object EventSource { get; set; }
}

自然,咱们理应规定独一默许的实现。EventData

/// 
/// 365投注平台源:描画365投注平台消息,用于参量发送信号
/// 
public class EventData : IEventData
{
    /// 
    /// 365投注平台发作的时期
    /// 
    public DateTime EventTime { get; set; }

    /// 
    /// 突然发出或出现365投注平台的反对
    /// 
    public Object EventSource { get; set; }

    public EventData()
    {
        EventTime = 
    }
}

捕捉演示,延长365投注平台源列举如下:

public class FishingEventData : EventData
{
    public FishType FishType { get; set; }
    public 渔人 FisingMan { get; set; }
}

成功后,咱们可以去把它放浮现。FishingRod公告的付托参量典型更代替FishingEventData典型了,即public delegate void FishingHandler(FishingEventData eventData); 宣言布置
继修正渔人Update该办法可以根据DE下定义的参量典型停止修正。,我不见得让编码消灭。,让咱们本身弥补大脑。。

到这一步咱们就一致了365投注平台源的下定义办法。

.使滴下365投注平台处置器

365投注平台源一致了,那365投注平台处置也得加以限度局限。比方免得恣意命名365投注平台处置办法名,那在停止365投注平台加入的时辰还要去比照付托下定义的参量典型去婚配,没成绩。。

咱们使滴下独一。IEventHandler啮合:

 /// 
 /// 下定义365投注平台处置器公共啮合,占大约365投注平台处置都要实现该啮合
 /// 
 public interface IEventHandler
 {
 }

365投注平台处置要与365投注平台源停止绑定,例如,让咱们下定义独一流通啮合。:

 /// 
 /// 泛型365投注平台处置器啮合
 /// 
 /// 
 public interface IEventHandler : IEventHandler where TEventData : IEventData
 {
     /// 
     /// 365投注平台处置器实现该办法来处置365投注平台
     /// 
     /// 
     void HandleEvent(TEventData eventData);
 }

你可能性会理解奇数的。,为什么咱们先下定义独一空啮合?让咱们把它留给咱们本身吧。。

像这样咱们就成功了365投注平台处置的抽象派的。让咱们持续翻转咱们的演示。。咱们让渔人实现IEventHandler啮合,继修正观察类。fishingRod.FishingEvent += jeff.Update;代替fishingRod.FishingEvent += jeff.HandleEvent;那就够了。编码更改很简略。,嗨省略了同一的情节。。

在这点上,您可能性触摸咱们早已成功了DEM的替换。。但实则呢?,咱们还必要廓清大约地成绩。渔人订阅的有宁静的365投注平台,咱们该怎地处置呢?
像你两者都有智力的,你指示方向地发生了。经过365投注平台源来停止区别处置

public class 渔人 : IEventHandler
{
    省略宁静编码
    public void HandleEvent(IEventData eventData)
    {
        if (eventData is FishingEventData)
        {
            //do something
        }

        if(eventData is XxxEventData)
        {
            //do something else
        }
    }
}

像这样,实现这点的时尚大部分地是流通的。。

4. 实现365投注平台公路

流通发行物订阅时尚缺点咱们的目的。,咱们的挥向是独一集中式的365投注平台处置机制,并且每个模块不相互信任。。这么咱们怎样才能做到呢?同一,咱们也要逐渐停止辨析和变革。。

.辨析成绩

想一想。,每回实现这种时尚,应成功以下三个提议。:

  1. 365投注平台发行物方下定义365投注平台付托
  2. 365投注平台订阅方下定义365投注平台处置逻辑
  3. 显示的订阅365投注平台

还是最适当的三个提议。,但这三个提议早已有趣了。。并且365投注平台发行物方和365投注平台订阅方还在着信任(体如今订阅者要显示的停止365投注平台的加入和登记上)。并且当365投注平台过多时,指示方向在用户中实现IEventHandler啮合处置多个365投注平台逻辑显然不太合身的,守法单一工作信条。嗨暴露出三个成绩。:

  1. 办法理想化提议?
  2. 咱们办法从订阅者发行物出版社?
  3. 办法克制不要在订阅者中同时处置多个365投注平台逻辑?

带成绩考虑,咱们将全部亲密的真理。。

想理想化提议,继咱们必要找到公共点。。个性执意365投注平台的实质,也执意咱们筹码365投注平台源和365投注平台处置使滴下浮现的两个啮合。

想宽恕信任,继咱们必要在出版社和订阅者当中添加中级的。。

残忍的克制不要订阅者同时处置过多365投注平台逻辑,那咱们就把365投注平台逻辑的处置使滴下到订阅者表面。

有一种思绪。,如今让咱们把它付诸实现。。

.处理成绩

根据埋头苦干的智慧,咱们将在下面处理前述的成绩。。

4.. EivithDand的实现

让咱们先处理第三个成绩。:办法克制不要在订阅者中同时处置多个365投注平台逻辑?

自然是筹码明显的的365投注平台源IEventData实现明显的IEventHandler。改革后的吸365投注平台处置逻辑列举如下:

/// 
/// 吸365投注平台处置
/// 
public class FishingEventHandler : IEventHandler
{
    public void HandleEvent(FishingEventData eventData)
    {
        eventData.渔人.FishCount++;

        ("{0}:使受限度局限A[ { 2 },{ 1 }鱼早已被使受限度局限。!",
            eventData.渔人.Name, eventData.渔人.FishCount, eventData.FishType);

    }
}

继咱们可以移除它。渔人在实现IEventHandler啮合了。
继将365投注平台加入代替fishingRod.FishingEvent += new FishingEventHandler().HandleEvent;那就够了。

4.. 一致加入365投注平台

处理不可更改的一个人题的办法,它帮忙咱们处理第独一成绩。:办法理想化工艺追逐?
为什么呢,因咱们是根据365投注平台源下定义相关联的的365投注平台处置的。也执意咱们先发制人说的可以根据365投注平台源来区别365投注平台。
继呢?反照,咱们可以经过反照来停止365投注平台的一致加入。
FishingRod在构成职务中应用反照,实现了一致表达。IEventHandler典型要求办法HandleEvent

public FishingRod()
{
    Assembly assembly = ();

    foreach (var) type in assembly.GetTypes())
    {
        if (typeof(IEventHandler).IsAssignableFrom(典型))//断定趋势典型条件实现了IEventHandler啮合
        {
            Type handlerInterface = (EvEnthDunl1);/ /获取该类实现的流通啮合
            Type eventDataType = ()[0]; // 获取泛型啮合指定的的参量典型。。

            免得参量典型是吸365投注平台知识,则阐明365投注平台源婚配
            if ((typeof(FishingEventData)))
            {
                安排要求
                var handler = (典型) as IEventHandler;
                //加入365投注平台
                FishingEvent += 
            }
        }
    }
}

大约,咱们可以从观察类中停止显示加入编码。fishingRod.FishingEvent += new FishingEventHandler().HandleEvent;

.3. 宽恕信任

办法宽恕信任呢?真正答案就在本文的两张图上,心细比得上,咱们可以很适于眼睛的地布告。,Event Bus就相当于独一中央状态Publisher和Subscriber中央的方法。它使绝缘了出版社和订阅者当正中鹄的指示方向信任相干。,改写者适应者了占有365投注平台的发行物和订阅逻辑,并符合365投注平台的转移。

Event 信息转移通路结果下台了。!!!
辨析一下,免得EventBus要改写者适应者占有365投注平台的发行物和订阅,那它则必要有独一货柜来记载365投注平台源和365投注平台处置。那又办法突然发出或出现呢?受胎365投注平台源,咱们就自然能找到绑定的365投注平台处置逻辑,反照被传授初步知识的。编码列举如下:

/// 
/// 365投注平台公路
/// 
public class EventBus
{
    public static EventBus Default => new EventBus();

    /// 
    /// 下定义穿成串保险集中
    /// 
    private readonly ConcurrentDictionary> _eventAndHandlerMapping;

    public EventBus()
    {
        _eventAndHandlerMapping = new ConcurrentDictionary>();
        MapEventToHandler();
    }

    /// 
    经过反照,将365投注平台源与365投注平台处置绑定
    /// 
    private void MapEventToHandler()
    {
        Assembly assembly = ();
        foreach (var) type in assembly.GetTypes())
        {
            if (typeof(IEventHandler).IsAssignableFrom(典型))//断定趋势典型条件实现了IEventHandler啮合
            {
                Type handlerInterface = (EvEnthDunl1);/ /获取该类实现的流通啮合
                if (handlerInterface != 空)
                {
                    Type eventDataType = ()[0]; // 获取泛型啮合指定的的参量典型。。

                    if ((eventDataType))
                    {
                        List handlerTypes = _eventAndHandlerMapping[eventDataType];
                        (典型)
                        _eventAndHandlerMapping[eventDataType] = handlerTypes;
                    }
                    else
                    {
                        var handlerTypes = new List { type };
                        _eventAndHandlerMapping[eventDataType] = handlerTypes;
                    }
                }
            }
        }
    }

    /// 
    /// 手工操作绑定365投注平台源与365投注平台处置
    /// 
    /// 
    /// 
    public void Register(典型) eventHandler)
    {
        List handlerTypes = _eventAndHandlerMapping[typeof(TEventData)];
        if (!(eventHandler))
        {
            (eventHandler);
            _eventAndHandlerMapping[typeof(TEventData)] = handlerTypes;
        }
    }

    /// 
    /// 手工操作破除365投注平台源与365投注平台处置的绑定
    /// 
    /// 
    /// 
    public void UnRegister(典型) eventHandler)
    {
        List handlerTypes = _eventAndHandlerMapping[typeof(TEventData)];
        if ((eventHandler))
        {
            (eventHandler);
            _eventAndHandlerMapping[typeof(TEventData)] = handlerTypes;
        }
    }

    /// 
    /// 根据365投注平台源突然发出或出现绑定的365投注平台处置
    /// 
    /// 
    /// 
    public void Trigger(TEventData eventData) where TEventData : IEventData
    {
        List handlers = _eventAndHandlerMapping[()];

        if (处置顺序) != null && handlers.Count > 0)
        {
            foreach (var) handler in 处置顺序)
            {
                MethodInfo methodInfo = ("HandleEvent");
                if (methodInfo != 空)
                {
                    object obj = (处置顺序)
                    (OBJ), new object[] { eventData });
                }
            }
        }
    }
}

365投注平台公路次要下定义三个办法,加入、移动加入、365投注平台突然发出或出现。常一些执意咱们在构成职务中经过反照去停止365投注平台源和365投注平台处置的绑定。
编码正文充分清楚的。,这公正的很多解说。。

下一步咱们将修正演示。,修正FishingRod的365投注平台突然发出或出现:

/// 
/// 下钩
/// 
public void ThrowHook(渔人 人)
{
    (启动下独一钩子)!");

    随机数位仿照鱼骨,免得随机数位是偶数,鱼咬伤
    if (新的 作任意排列(下) % 2 == 0)
    {
        var a = new 随机(10)。
        var type = (FishType)new 作任意排列()(下一步(0), 5);
        (贝尔):叮叮叮,鱼咬人。
        if (FishingEvent != 空)
        {
            var eventData = new FishingEventData() { FishType = type, 渔人 = man };
            //FishingEvent(eventData);//不再必要经过365投注平台付托突然发出或出现
            (eventData);//指示方向经过365投注平台公路突然发出或出现那就够了
        }
    }
}

像这样,365投注平台公路的雏形早已塑造!

5.365投注平台公路的总结

经过下提议的辨析和业务,发明365投注平台公路也缺点什么深邃的理念,预备咱们擅长考虑。,勤勤恳恳,也能实现本身的365投注平台公路。
根据咱们的实现,可能性总结列举如下。:

  1. 365投注平台公路技术维护独一365投注平台源与365投注平台处置的熭字典;
  2. 经过单时尚,确保365投注平台公路的要不是门口;
  3. 使用反照成功365投注平台源与365投注平台处置的设定初值绑定;
  4. 预备一致的365投注平台加入、移动加入和突然发出或出现啮合。

不可更改的,下365投注平台公路的实现公正的独一雏形,有很多潜在的成绩。。免得你感兴趣,想想看,并改良它。,我会不息的花样翻新和使完善。,纵情等待!


参考资料

ABP EventBus
DDD~军事]野战的365投注平台与365投注平台公路
DDD365投注平台公路的实现

发表评论

电子邮件地址不会被公开。 必填项已用*标注