文档章节

C# 通过委托实现两个程序集间的双向调用

北风其凉
 北风其凉
发布于 2016/05/08 00:24
字数 774
阅读 433
收藏 5

这个问题是我在今天的工作中遇到的。有两个C#程序集,主程序集的窗口甲要调用副程序集的窗口乙,主程序集引用了副程序集。现在的问题是,窗口甲打开窗口乙后,除要实现窗口甲调用窗口乙的内容外,窗口乙也需要调用窗口甲的功能。

现在主程序集引用了副程序集,自然可以实现窗口甲调用窗口乙内的功能。但副程序集已经不能再引用主程序集,因为这样会造成循环依赖的情况,这是VS所不允许的。

经过一番研究,我发现使用委托可以很容易地完成上述功能。现将DEMO程序讲解如下:

其中AssemblyTest1就是上面说的程序集甲,AssemblyTest2是程序集乙。AssemblyTest1引用了AssemblyTest2。

FormMain是程序集AssemblyTest1的主窗体,里面只有一个按钮,功能是打开AssemblyTest2的主窗体FormTest。

FormMain的代码如下:

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 AssemblyTest1
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        AssemblyTest2.FormTest formTest = new AssemblyTest2.FormTest();

        private void FormMain_Load(object sender, EventArgs e)
        {
            formTest = new AssemblyTest2.FormTest();
            formTest.GeneratePoem += (obj, poem) =>
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine(poem.title + "," + poem.author);
                    sb.AppendLine(poem.sentence1 + ",");
                    sb.AppendLine(poem.sentence2 + "。");
                    sb.AppendLine(poem.sentence3 + ",");
                    sb.AppendLine(poem.sentence4 + "。");
                    MessageBox.Show(sb.ToString());
                };
        }

        private void btnOpenFormTest_Click(object sender, EventArgs e)
        {
            formTest.InitPoem(
                "江雪", "柳宗元", 
                "千山鸟飞绝",
                "万径人踪灭",
                "孤舟蓑笠翁", 
                "独钓寒江雪");
            formTest.Show();
        }
    }
}

FormTest是被FormMain中按钮打开的窗体,它位于AssemblyTest2程序集内。为了实现调用FormMain的功能,我将逻辑实现在了FormMain中(即formTest.GeneratePoem后面的那个Lambda表达式)。

FormTest代码如下:

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 AssemblyTest2
{
    public partial class FormTest : Form
    {
        public FormTest()
        {
            InitializeComponent();
        }

        public void InitPoem(string title, string author, 
            string s1, string s2, string s3, string s4)
        {
            this.txtTitle.Text = title;
            this.txtAuthor.Text = author;
            this.txtSentence1.Text = s1;
            this.txtSentence2.Text = s2;
            this.txtSentence3.Text = s3;
            this.txtSentence4.Text = s4;
        }

        /// <summary>
        /// 定义委托类
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="data"></param>
        public delegate void AssemblyTestCustomHandle(object sender, Poem poem);
        /// <summary>
        /// 获取古诗内容
        /// </summary>
        public event AssemblyTestCustomHandle GeneratePoem;

        /// <summary>
        /// 生成古诗内容 - FormMain订阅了该事件后即可获取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnNotifyFormMain_Click(object sender, EventArgs e)
        {
            if (GeneratePoem != null)
            {
                Poem poem = new Poem();
                poem.title = this.txtTitle.Text;
                poem.author = this.txtAuthor.Text;
                poem.sentence1 = this.txtSentence1.Text;
                poem.sentence2 = this.txtSentence2.Text;
                poem.sentence3 = this.txtSentence3.Text;
                poem.sentence4 = this.txtSentence4.Text;
                GeneratePoem(this, poem);
            }
        }

        private void FormTest_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            this.Hide();
        }
    }
}

点击按钮btnNotifyFormMain后,会进入事件GeneratePoem,而这个事件是在FormMain中实现的,这等于变相调用了FormMain中的逻辑,FormMain中实现的逻辑自然也可以调用FormMain窗体中的一些全局变量等内容。

程序运行效果图如下:

1、在FormMain中点击“打开测试窗体”按钮,弹出“被调用窗体”FormTest

2、在“被调用窗体”中点击“调用主窗体逻辑”按钮后,“被调用窗体”中的各项参数此时被传递到主窗体,并由主窗体按自身逻辑拼接成串,通过MessageBox予以输出。

END

© 著作权归作者所有

共有 人打赏支持
北风其凉

北风其凉

粉丝 115
博文 498
码字总数 463468
作品 4
朝阳
程序员
Adapter 适配器模式

动机 适配器模式是类和对象之间的适配。同现实生活中的适配器一样,它用于两个物体间的接合和桥接。现实生活里我们有电源适配器,相机的内存卡适配器等。或许每个人都见过一些内存卡的适配器...

holysu
2017/07/11
0
0
c#中的反射机制

反射的概述: 反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义...

云栖希望。
2017/12/04
0
0
C# WPF 通过委托实现多窗口间的传值

在使用WPF开发的时候就不免会遇到需要两个窗口间进行传值操作,当然多窗口间传值的方法有很多种,本文介绍的是使用委托实现多窗口间的传值。 在上代码之前呢,先简单介绍一下什么是C#中的委托...

hello黄先森
08/30
0
0
.NET面试题解析(05)-常量、字段、属性、特性与委托

转自:http://www.cnblogs.com/anding/p/5255492.html 常见面试题目: 1. const和readonly有什么区别? 2. 哪些类型可以定义为常量?常量const有什么风险? 3. 字段与属性有什么异同? 4. 静态...

莫问今朝乄
02/01
0
0
在.NET中利用委托实现窗体间安全通信

对于窗体间简单的通信,采用VB6.0的方法就能满足我们的要求,但在一些架构设计复杂的应用中,这种方法就显得有点捉襟见肘了,同时该方法还有一个缺点,就是它仅仅对通过.NET窗体向导添加进去...

老朱教授
2017/11/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux 系统的运行级别

运行级别 运行级别 | 含义 0 关机 1 单用户模式,可以想象为windows 的安全模式,主要用于修复系统 2 不完全的命令模式,不含NFS服务 3 完全的命令行模式,就是标准的字符界面 4 系统保留 5 ...

Linux学习笔记
今天
2
0
学习设计模式——命令模式

任何模式的出现,都是为了解决一些特定的场景的耦合问题,以达到对修改封闭,对扩展开放的效果。命令模式也不例外: 命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。 解决了这...

江左煤郎
今天
3
0
字典树收集(非线程安全,后续做线程安全改进)

将500W个单词放进一个数据结构进行存储,然后进行快速比对,判断一个单词是不是这个500W单词之中的;来了一个单词前缀,给出500w个单词中有多少个单词是该前缀. 1、这个需求首先需要设计好数据结...

算法之名
昨天
15
0
GRASP设计模式

此文参考了这篇博客,建议读者阅读原文。 面向对象(Object-Oriented,OO)是当下软件开发的主流方法。在OO分析与设计中,我们首先从问题领域中抽象出领域模型,在领域模型中以适当的粒度归纳...

克虏伯
昨天
1
0
Coding and Paper Letter(四十)

资源整理。 1 Coding: 1.Tomislav Hengl撰写的非官方作者指南:Michael Gould•Wouter Gerritsma。 UnofficialGuide4Authors 2.R语言包rwrfhydro,社区贡献的工具箱,用于管理,分析和可视化...

胖胖雕
昨天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部