c#中通过 Easy.MessageHub实现类似aardio的subsciribe和publish功能

By admin at 2023-04-06 • 0人收藏 • 881人看过

一直觉得aardio里的订阅功能很好用, 一对多 / 多对一, 减少了系统间的耦合,

那么在c#中应该怎么实现呢?

最简单的方法是调用 Easy.MessageHub 程序集

开源地址 https://github.com/NimaAra/Easy.MessageHub

源码本地下载:

Easy.MessageHub-master.zip


1.声明一个静态类, 存储公共头

internal class comPS
{
   public static IMessageHub hub = new MessageHub();
}


2. Form1中订阅

public Form1()
{
    CheckForIllegalCrossThreadCalls = false;
    InitializeComponent();
    comPS.hub.Subscribe<string>(p => {
        textBox1.Text = p; 
        button1.Text = p; 
    });
}


3. from2中发布

private void button1_Click(object sender, EventArgs e)
{
    comPS.hub.Publish<string>("com form 2");
}



如果需要区分不同的消息处理不同的功能, 那么可以订阅里判定接收到的string


Easy.MessageHub.zip





升级类库到了.net8.0, 

工程源码如下: 

链接:https://pan.baidu.com/s/10sGPqWq0fFgpMZgKmb4HoA?pwd=nr96 

提取码:nr96


image.png

image.png

hub.Publish(new Person { Id = "Foo" });
hub.Publish("An important message");


12 个回复 | 最后更新于 2023-04-22
2023-04-06   #1

??aardio里的订阅功能???

有什么订阅功能?

2023-04-06   #2

回复#1 @hi_aardio :

.......

我说的和你想的不一样. 我说的是

subscribe("",function(...){
	
} )
publish("",)

image.png

这个功能.....

不是你所想的订阅

2023-04-21   #3

回复#2 @admin :

其实C#原生就支持“消息订阅/发布”功能,不需要第三方库支持的。


C#实现的方式是通过 Delegate 代理方式,在消息订阅的地方创建Delegate,在消息发布的地方调用创建的Delegate就可以实现。


如果有需要我晚点可以传一个example上来

2023-04-21   #4

回复#3 @jerrxjr1220 :

需要个示例

我试了它这个还是蛮灵活舒服的.

2023-04-21   #5

回复#2 @admin :

请教一下这个东西常用在什么场景?

2023-04-21   #6

好吧,我查了下gpt

Delegate(代理)在C#中用于封装对方法的引用。它允许将方法视为可分配给变量或作为参数传递的实体。delegate关键字用于定义delegate类型。它指定可由该delegate封装的方法的返回类型和参数。例如:

csharp
delegate int MathDelegate(int a, int b);

这个delegate可以封装接受两个int并返回int的任何方法。使用delegate的步骤:1. 定义delegate类型,指定方法签名;2. 声明delegate变量;3. 将方法赋值给delegate变量;4. 调用delegate变量就像调用方法一样;5. 实际调用的将是delegate变量封装的方法。示例:

csharp
delegate int MathDelegate(int a, int b);

class DelegateDemo 
{
    static int Add(int a, int b)
    {
        return a + b;
    }
    
    static int Sub(int a, int b)
    {
        return a - b;
    }
    
    static void Test()
    {
        MathDelegate delegate1 = Add;
        MathDelegate delegate2 = Sub;
        
        int result = delegate1(1, 2);   // Calls Add(1, 2)
        Console.WriteLine(result);      // Prints 3
        
        result = delegate2(5, 2);      // Calls Sub(5, 2)
        Console.WriteLine(result);      // Prints 3
    }
}

这里我们定义了一个MathDelegate delegate类型,用于封装接受两个int并返回int的方法。然后我们创建两个该delegate类型的变量delegate1和delegate2,并将Add和Sub方法分别赋值给它们。最后调用delegate1和delegate2就像调用Add和Sub方法一样,实际上调用的也是这两个方法。所以delegate允许我们将方法视为可传递和执行的实体,从而实现回调和事件处理等功能。



2023-04-21   #7

回复#6 @hi_aardio :

关键在于别的界面调用这个委托, 比如从mainform里弹出来一个dialogForm, 要这个dialogform里去按下mainform里面的一个button , 更甚者 , 也许还有其他界面也要这样操作mainfrom里面的这个button , 就是多对一 ,和一对多

用委托这样直接写, 忒麻烦

最后我才用的这个messagehub库, 方便多了

2023-04-21   #8

回复#7 @admin :

Delegate的使用方法见主窗体代码注释。

假设我的程序里有2个窗体,我希望在一个子窗体中控制另一个子窗体的显示

子窗体1:


子窗体2:

主窗体:

主窗体代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TabWinForm
{
    public partial class Form1 : Form
    {
        private Point mPoint;
        FormTab1 formTab1;
        FormTab2 formTab2;

        //1. 定义委托,可以直接使用 Action<T> 或者 Func<T> 内建的委托类型,省略步骤1.
        //public delegate void ChangeLogoDelegate(string logo);
        //2. 构建委托的方法
        public void ChangeLogo(string logo)
        {
            formTab1.txtUrl.Text = logo;
        }
        //3. 创建委托变量(哪里使用,哪里创建)【见子窗体】
        //4. 使用委托 【见子窗体】

        public Form1()
        {
            InitializeComponent();
            formTab1 = new FormTab1();
            formTab1.TopLevel = false;
            formTab1.Dock = DockStyle.Fill;
            formTab2 = new FormTab2();
            formTab2.TopLevel = false;
            formTab2.Dock = DockStyle.Fill;

            btnTab1_MouseClick(null, null);
            //5. 关联委托
            formTab2.changeLogo += ChangeLogo;
        }
        

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnMin_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
            this.notifyIcon1.Visible = true;
        }

        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
            this.notifyIcon1.Visible = false;
        }

        private void btnTab1_MouseClick(object sender, MouseEventArgs e)
        {
            btnTab2.BackColor = Color.DodgerBlue;
            btnTab1.BackColor = Color.Navy;

            splitContainer2.Panel2.Controls.Clear();
            formTab1.Parent = splitContainer2.Panel2;
            formTab1.Show();
        }

        private void btnTab2_MouseClick(object sender, MouseEventArgs e)
        {
            btnTab1.BackColor = Color.DodgerBlue;
            btnTab2.BackColor = Color.Navy;

            splitContainer2.Panel2.Controls.Clear();
            formTab2.Parent = splitContainer2.Panel2;
            formTab2.Show();
        }

        private void splitContainer1_Panel1_MouseDown(object sender, MouseEventArgs e)
        {
            mPoint = new Point(e.X, e.Y);
        }

        private void splitContainer1_Panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Location = new Point(this.Location.X+e.X-mPoint.X, this.Location.Y+e.Y-mPoint.Y);
            }
            
        }

        private void btnTab1_MouseHover(object sender, EventArgs e)
        {
            slide.Top = btnTab1.Top;
        }

        private void btnTab2_MouseHover(object sender, EventArgs e)
        {
            slide.Top = btnTab2.Top;
        }

        
    }
}

子窗体1代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TabWinForm
{
    public partial class FormTab1 : Form
    {
        string text;

        
        public FormTab1()
        {
            InitializeComponent();
            
        }

        private void btnGet_ClickAsync(object sender, EventArgs e)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, txtUrl.Text);
            request.Headers.UserAgent.ParseAdd("Mozilla");
            var client = new HttpClient();
            var response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
            txtResult.Text = response.Content.ReadAsStringAsync().Result;
        }
    }
}

子窗体2代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static TabWinForm.FormTab1;

namespace TabWinForm
{
    public partial class FormTab2 : Form
    {
        //3. 创建委托变量
        public Action<string> changeLogo;
        public FormTab2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //4. 使用委托
            changeLogo(@"https://www.baidu.com");
        }
    }
}


2023-04-21   #9

回复#7 @admin :

因为委托(代理)可以通过

//5. 关联委托
            formTab2.changeLogo += ChangeLogo;

的方式关联多个委托(代理)方法,所以可以实现一对多或者多对一的“发布/订阅”功能。


B站上有详解事件和委托的关系,可以去看看

C# 的委托与事件大致是怎么一回事_哔哩哔哩_bilibili

2023-04-21   #10

回复#7 @admin :

其实委托用熟了还是很方便的,常规的步骤:

  1. 创建委托方法   -> 订阅功能

  2. 创建委托(哪里使用,哪里创建)

  3. 使用委托         -> 发布功能

  4. 把委托和委托方法进行关联


和“订阅/发布”没什么不同,只是多一步“委托关联”,这也是C# 事件的常用方法。C#的事件其实本质上也是一种委托,是限定权限为private的委托。

2023-04-21   #11

回复#10 @jerryxjr1220 :

多谢 ,每次用form2.changelog+=……这种方式来关联用起来很不舒服,感觉这个form2类似 实名举报 ,我必须要关联这个form2,没有aar这里的subcribe这种匿名方式方便。

2023-04-22   #12

回复#11 @admin :

aardio里的subcribe应该是老大写的语法糖,底层的话肯定还是有个关联的逻辑

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...