你的位置:首页 > ASP.net教程

[ASP.net教程]Lind.DDD.Events事件总线~自动化注册


回到目录

让大叔兴奋的自动化注册

对于领域事件之前说过,在程序启动时订阅(注册)一些事件处理程序,然后在程序的具体位置去发布(触发)它,这是传统的pub/sub模式的体现,当然也没有什么问题,为了让它支持分布式的场景,我们引用了redis这种存储介质,这一切都早已集成到了Lind.DDD架构中,对些没什么好说的,而今天的重点在于"事件的自动过注册"的理念,这个概念真实在ABP架构中出现了,大叔觉得很不错,所以也集成到了自己的架构中,为些也兴奋了一段时间,其中有解决问题的

Redis只是一种分布式存储介质

对于第一版将事件总线放到内存的情况来说,使用redis这种存储介质确实解决了分布式的事件问题,它可以在更多场合下使用,不用考虑WEB端的负载均衡,不用考虑服务端的存储压力,不用考虑并发时的吞吐量,确实,redis是个存储效率非常高的产物,大叔redis里的事件的Key采用了当前EventData的名字加上自定义的前缀,这样可以同时在多个项目中使用.

     /// <summary>    /// 对于事件数据的存储,目前采用内存字典    /// </summary>    private readonly IRedisClient _redisClient = RedisManager.GetClient();    /// <summary>    /// redis事件总线的Key    /// </summary>    private string redisKey = ConfigConstants.ConfigManager.Config.DomainEvent.RedisKey;    /// <summary>    /// 得到当前redis-eventbus-key    /// </summary>    /// <typeparam name="TEvent"></typeparam>    /// <returns></returns>    private string GetCurrentRedisKey<TEvent>()    {      return redisKey + "_" + typeof(TEvent).FullName;    }    /// <summary>    ///得到非泛型版本的值    /// </summary>    /// <param name="tEvent"></param>    /// <returns></returns>    private string GetCurrentRedisKey(Type tEvent)    {      return redisKey + "_" + tEvent.FullName;    }

结构图

主角是SubscribeAll这个方法

对于当前应用程序下的所有DLL进行反射,拿到所有实现了IEventHandler的类型,然后对这么类型(事件处理程序)进行注册即可.

核心代码(Memory版):

    /// <summary>    /// 需要过滤的接口    /// </summary>    string[] Excepts = { "IEventHandler`1", "ActionDelegatedEventHandler`1" };    /// <summary>    /// 全局统一注册所有事件处理程序,实现了IEventHandlers的    /// </summary>    public void SubscribeAll()    {      var types = AppDomain.CurrentDomain.GetAssemblies()         .SelectMany(a => a.GetTypes()         .Where(t => t.GetInterfaces().Contains(typeof(IEventHandlers))))         .Where(i => !Excepts.Contains(i.Name))         .ToArray();      foreach (var item in types)      {        if (!item.ContainsGenericParameters)        {          var en = Activator.CreateInstance(item);          foreach (var t in item.GetInterfaces().Where(i => i.Name != "IEventHandlers"))          {            Subscribe(t, en);          }        }      }    }    /// <summary>    /// 订阅非泛型版    /// </summary>    /// <param name="type"></param>    /// <param name="eventHandler"></param>    void Subscribe(Type type, object eventHandler)    {      lock (_objLock)      {        var eventType = type.GetGenericArguments()[0];        //var eventType = type.GetType().GenericTypeArguments[0];        if (_eventHandlers.ContainsKey(eventType))        {          var handlers = _eventHandlers[eventType];          if (handlers != null)          {            if (!handlers.Exists(deh => _eventHandlerEquals(deh, eventHandler)))              handlers.Add(eventHandler);          }          else          {            handlers = new List<object>();            handlers.Add(eventHandler);          }        }        else          _eventHandlers.Add(eventType, new List<object> { eventHandler });      }    }

对于这种仓储,在Redis里事实上是以二进制的格式存储的,所以要求你的EventData和EventHandler需要标记为可序列化,我经过测试,对于Json序列化的方式,在进行发布时,不能成功回调"订阅"的代码,原因我目前还不清楚,需要大家一起去研究!

去三亚的旅游团价格去三亚旅游必去景点去三亚旅游要多少钱去三亚旅游最佳路线去三亚旅游最佳时间北京后海在哪?怎么去? 什么时候去桂林最好?什么时候去桂林最适合旅游? 暑假一个人去云南旅游大概需要多少钱? 北海公园在哪?怎么去? 清远英西峰林走廊好玩吗? 惠州也有西湖吗?惠州西湖怎么样? 清远英西峰林走廊在哪?怎么去? 惠州海滨温泉好玩吗? 峨眉山在四川哪里 武当山景区门票价格多少钱_武当山票价及开放时间 无锡唐城旅游景点介绍 日本樱花节 深圳小梅沙海洋公园票价?小梅沙海洋世界优惠价? 深圳小梅沙海洋世界图?小梅沙海洋世界特色? 深圳小梅沙海洋世界有直达车吗?小梅沙海洋世界在哪里坐车? 广州花都香草世界图片?花都香草世界漂亮吗? AC16DIF Datasheet AC16DIF Datasheet AC245 Datasheet AC245 Datasheet AC25DIR Datasheet AC25DIR Datasheet 去昆明旅游 去昆明旅游 去昆明旅游 阿布扎比迪拜 阿布扎比迪拜 阿布扎比迪拜 苏丹签证 苏丹签证 苏丹签证