前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WPF中实现Eventbus

WPF中实现Eventbus

作者头像
码客说
发布2020-07-14 10:32:29
8180
发布2020-07-14 10:32:29
举报
文章被收录于专栏:码客码客

前言

在开发Android或Vue前端的时候,我们可能数据产生后需要在多个页面接收,这时候可以用EventBus来实现,那么WPF开发能用EventBus吗?我没就来尝试一下!

EventBus

事件实体类

using System;

namespace SchoolClient.Utils.EventBus
{
    /// <summary>
    /// 定义事件源接口,所有的事件源都要实现该接口
    /// </summary>
    public interface IEventData
    {
        /// <summary>
        /// 事件发生的时间
        /// </summary>
        DateTime EventTime { get; set; }

        /// <summary>
        /// 触发事件的对象
        /// </summary>
        object EventSource { get; set; }
    }

    public class EventData : IEventData
    {
        /// <summary>
        /// 事件发生的时间
        /// </summary>
        public DateTime EventTime { get; set; }

        /// <summary>
        /// 触发事件的对象
        /// </summary>
        public Object EventSource { get; set; }

        public EventData()
        {
            EventTime = DateTime.Now;
        }
    }
}

事件处理类接口

namespace SchoolClient.Utils.EventBus
{
    public interface IEventHandler
    {
    }

    public interface IEventHandler<TEventData> : IEventHandler where TEventData : IEventData
    {
        /// <summary>
        /// 事件处理器实现该方法来处理事件
        /// </summary>
        /// <param name="eventData"></param>
        void HandleEvent(TEventData eventData);
    }
}

EventBus


using SchoolClient.Utils.EventBus;

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection;

namespace SchoolClient.Utils
{
    /// <summary>
    /// 事件总线
    /// </summary>
    public class ZEventBus
    {
        public static ZEventBus Instance = new ZEventBus();

        /// <summary>
        /// 定义线程安全集合
        /// </summary>
        private readonly ConcurrentDictionary<Type, List<Type>> _eventAndHandlerMapping;

        public ZEventBus()
        {
            _eventAndHandlerMapping = new ConcurrentDictionary<Type, List<Type>>();
        }

        // 注册所有的事件
        public void RegisterAll() {
            Assembly assembly = Assembly.GetEntryAssembly();
            foreach (var type in assembly.GetTypes())
            {
                if (typeof(IEventHandler).IsAssignableFrom(type))//判断当前类型是否实现了IEventHandler接口
                {
                    Type handlerInterface = type.GetInterface("IEventHandler`1");//获取该类实现的泛型接口
                    if (handlerInterface != null)
                    {
                        Type eventDataType = handlerInterface.GetGenericArguments()[0]; // 获取泛型接口指定的参数类型
                        if (_eventAndHandlerMapping.ContainsKey(eventDataType))
                        {
                            List<Type> handlerTypes = _eventAndHandlerMapping[eventDataType];
                            handlerTypes.Add(type);
                            _eventAndHandlerMapping[eventDataType] = handlerTypes;
                        }
                        else
                        {
                            var handlerTypes = new List<Type> { type };
                            _eventAndHandlerMapping[eventDataType] = handlerTypes;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 手动绑定事件源与事件处理
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="eventHandler"></param>
        public void Register<TEventData>(Type eventHandler)
        {
            List<Type> handlerTypes;
            if (_eventAndHandlerMapping.ContainsKey(typeof(TEventData)))
            {
                handlerTypes = _eventAndHandlerMapping[typeof(TEventData)];
            }
            else {
                handlerTypes = new List<Type>();
            }
            if (!handlerTypes.Contains(eventHandler))
            {
                handlerTypes.Add(eventHandler);
            }
            _eventAndHandlerMapping[typeof(TEventData)] = handlerTypes;
        }

        /// <summary>
        /// 手动解除事件源与事件处理的绑定
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="eventHandler"></param>
        public void UnRegister<TEventData>(Type eventHandler)
        {
            if (_eventAndHandlerMapping.ContainsKey(typeof(TEventData))) {
                List<Type> handlerTypes = _eventAndHandlerMapping[typeof(TEventData)];
             
                if (handlerTypes.Contains(eventHandler))
                {
                    handlerTypes.Remove(eventHandler);
                    _eventAndHandlerMapping[typeof(TEventData)] = handlerTypes;
      
                }
            } 
        }

        /// <summary>
        /// 根据事件源触发绑定的事件处理
        /// </summary>
        /// <typeparam name="TEventData"></typeparam>
        /// <param name="eventData"></param>
        public void PostEvent<TEventData>(TEventData eventData) where TEventData : IEventData
        {

            if (_eventAndHandlerMapping.ContainsKey(eventData.GetType()))
            {
                List<Type> handlers = _eventAndHandlerMapping[eventData.GetType()];
                if (handlers != null && handlers.Count > 0)
                {
                    foreach (var handler in handlers)
                    {
                        MethodInfo methodInfo = handler.GetMethod("HandleEvent");
                        if (methodInfo != null)
                        {
                            object obj = Activator.CreateInstance(handler);
                            methodInfo.Invoke(obj, new object[] { eventData });
                        }
                    }
                }
            }
        }
    }
}

项目中使用

数据

namespace SchoolClient.Socket
{
    public class SocketEvent : EventData
    {
        public ZWsMsgVo Msg { get; set; }

        public SocketEvent()
        {
        }
    }
}

项目中Event接收类

class MyClass : IEventHandler<SocketEvent>
{
    public void HandleEvent(SocketEvent eventData)
    {
        var msg = JsonConvert.SerializeObject(eventData);
        Console.WriteLine("EventBus:"+ msg); 
    }
}

只要调用

ZEventBus.Instance.RegisterAll();

或者

ZEventBus.Instance.Register<SocketEvent>(GetType());

这两种的任何一种方式注册后,都会收到事件

发送事件

ZEventBus.Instance.PostEvent<SocketEvent>(msgEvent);

问题

注意这个代码

MethodInfo methodInfo = handler.GetMethod("HandleEvent");
if (methodInfo != null)
{
    object obj = Activator.CreateInstance(handler);
    methodInfo.Invoke(obj, new object[] { eventData });
}

我们可以看出上面的实现的原理是通过反射找到类里的方法,然后创建类的实例调用其中的HandleEvent方法,所以问题就来了,我们没法用在Window对应的类上,因为该类无法在非UI线程中创建。

那么是不是可以直接保留类实例的引用,然后进行调用呢?

答案是不能

在运行时Window的子类通过一下方式获取Type

obj.GetType();

获取到的都是System.RuntimeType,也无法通过强转调用其中的方法。

所以目前还未实现能在Window的子类中使用EventBus

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • EventBus
  • 项目中使用
  • 问题
相关产品与服务
事件总线
腾讯云事件总线(EventBridge)是一款安全,稳定,高效的云上事件连接器,作为流数据和事件的自动收集、处理、分发管道,通过可视化的配置,实现事件源(例如:Kafka,审计,数据库等)和目标对象(例如:CLS,SCF等)的快速连接,当前 EventBridge 已接入 100+ 云上服务,助力分布式事件驱动架构的快速构建。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档