这个问题是我在今天的工作中遇到的。有两个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; } ////// 定义委托类 /// /// /// public delegate void AssemblyTestCustomHandle(object sender, Poem poem); ////// 获取古诗内容 /// public event AssemblyTestCustomHandle GeneratePoem; ////// 生成古诗内容 - FormMain订阅了该事件后即可获取 /// /// /// 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