专栏首页码客WPF中实现Eventbus

WPF中实现Eventbus

前言

在开发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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Electron中调用DLL

    NodeJS地址:https://nodejs.org/en/download/ Electron版本: https://electronjs.org/rele...

    剑行者
  • Android OkGo网络请求库 自定义回调支持带泛型的对象

    这里写了两种方式请求接口 (文中用了Java和Kotlin两种语言 没有特殊标示的都是Java)

    剑行者
  • Android中延时任务与定时任务

    AndroidL开始repeat的周期必须大于60秒 所以短周期循环执行不建议使用

    剑行者
  • C# http Get/POST请求封装类

    http://www.sufeinet.com/thread-3-1-1.html

    跟着阿笨一起玩NET
  • json使用实例二

    上面是我们在上一篇文章中请求返回来的JSON字符串,那么我们现在要解析他。第一步就是要根据这个JSON来写出对应的实体类。用来存放数据。这个实体类如何写的?其实...

    zls365
  • Magicodes.WeiChat——发送模板消息

    在微信开发中,经常会使用到模板消息。因此框架中对此进行了一些封装,并且提供了后台操作界面以及日志查看等功能,下面开始逐步介绍开发操作以及使用。

    雪雁-心莱科技
  • GenericFactoryMethod泛型工厂模式实现简单IOC功能

    泛型工厂理论上不算Gof23中设计模式之一,但是也算是一种非常好的设计模式,个人认为,废话不多说,先写个简单的抽象工厂,在写一个泛型工厂的例子来比较抽象和泛型的...

    郑小超.
  • 【015期】JavaSE面试题(十五):网络IO流

    大家好,我是Java面试题库的提裤姐,今天这篇是JavaSE系列的第十五篇,主要总结了Java中的IO流的问题,IO流分为两篇来讲,这篇是第二篇,主要是网络IO...

    java进阶架构师
  • 3分钟教你搭建 gitea 在 Centos 服务器

    本文告诉大家如何在一个 Centos 服务器上搭建 gitea 然后在 gitea 创建帐号上传代码

    林德熙
  • 看完此文你就学会了代理模式

    一个委托类,一个代理类,实现相同的接口,通常是在代理类中有一个委托类的对象,代理类并不会真正的执行方法,只是在委托类执行方法之前或之后提供一些服务。比如账户验证...

    秃头哥编程

扫码关注云+社区

领取腾讯云代金券