当前位置:K88软件开发文章中心编程语言.NET.NET01 → 文章内容

循环引用的解决方法

减小字体 增大字体 作者:佚名  来源:翔宇亭IT乐园  发布时间:2018-12-31 11:14:24

:2010-01-28 07:58:00

项目架构:

系统中的各功能都是分开在每个dll中实现的,主程序中加载各个菜单对应的dll。对于一些重复性比较高的功能代码,可以写在一个主dll里供其他功能调用,直接引用主dll就可以实现。

 

Main.exe           主程序。

Core.dll              公共接口和存贮缓存等。

T1.dll                  功能1

T2.dll                  功能2

 

现在项目有这样的需求:

要求两个功能之间相互调用,即T1.dll中在T1.MainForm中点击Button1去调用T2.dllT2.MainForm中的相应功能,反之亦然,T2.MainForm点击Button1调用T1.dll功能。

这时就遇到了问题,直接在工程中引用dll就会出现循环引用。所以得另辟蹊径。

 

解决方案:

利用反射调用dll,就避免了循环引用。不同功能间的相互通信可通过接口来解决。

 

具体实现:

Main.exe中用反射加载各个功能菜单,对各个Form进行实例化,缓存起来供其他功能调用。入口和实例均存在Core.MenuFactory.htMenu这个HashTable中。

 

再构造接口IInteraction

           接口IInteraction
publicinterface IInteraction
{
///<summary>
/// 简单的交互
///</summary>
void InterAction();

///<summary>
/// 高级交互,可传递参数
///</summary>
///<param name="args"></param>
void InterAction(object [] args);
}


T1.MainFormT2.MainForm均继承IInteraction。

            T1.MainForm中接口实现
#region IInteraction接口实现
publicvoid InterAction()
{

}

publicvoid InterAction(object[] args)
{
//参数类型转换
string args0 = (string)args[0];
string args1 = (string)args[1];
...

this.Text ="T1.MainForm被调用"+ args0 +""+ args1;
this.Activate();
}

#endregion

这里使用带参数的交互做示例,在T2.MainForm中点击Button1的时候,只要传入相应的参数即可。

  在T2.MainForm中Button1_Click()代码如下

            T2.MainForm中Button1_Click()
privatevoid Button1_Click(object sender, EventArgs e)
{
...

Core.Interface.IInteraction T1MainForm
=null;
T1MainForm
= (Core.Interface.IInteraction)Core.MenuFactory.htMenu["T1.MainForm"];
if (T2MainForm ==null)
{
//T2.MainForm未启动,则启动之
Core.ExecuteCommand.run("T1.MainForm", "T1.dll");
Button1_Click(sender, e);
}

else
{
string args0 ="a";
string args1 ="b";

T1MainForm.InterAction(
newobject[] { args0, args1 }
);
}

}


Core.dll中加载dll的代码如下:

T2.MainForm中接口实现参考T1.MainForm中接口实现。

T1.MainForm.Button1_Click()实现参考T2.MainForm.Button1_Click()

 

总结:

通过反射解决循环引用,dll的加载都在主工程中进行,就避免了dll循环引用会导致的文件争用问题,即解决了循环引用。

           Core.ExecuteCommand.run()
publicstaticvoid run(string className, string assambleName)
{
Assembly assem
=null;
System.Type type
=null;

if (assambleName.Length ==0)
{
thrownew Exception("......");
}


//读取本地文件
assem = Assembly.LoadFile(Core.Config.ApplicationConfig.getProperty("ApplicationRootPath") +"\\"+ assambleName);

type
= assem.GetType(className);
object Obj = System.Activator.CreateInstance(type);
Form obj;
if (Obj is Form)
{
obj
= (Form)Obj;
}

else
{
thrownew Exception("......");
}


Core.MenuFactory.AddMenu(className, obj);

obj.StartPosition
= System.Windows.Forms.FormStartPosition.CenterScreen;
if (Core.Config.ApplicationConfig.getProperty("WindowsStyle").CompareTo("WINDOWS") ==0)
{
if (Core.Config.ApplicationConfig.getProperty("WindowsPopupStyle").CompareTo("NORMAL") ==0)
{
obj.Show();
}

else
{
obj.ShowDialog();
}

}

else
{
obj.Show(Core.Config.ApplicationConfig.getWorkbench().DockPanel);
}

obj.Focus();
}


循环引用的解决方法