項目架構:
系統中的各功能都是分開在每個dll中實現的,主程序中加載各個菜單對應的dll。對于一些重復性比較高的功能代碼,可以寫在一個主dll里供其他功能調用,直接引用主dll就可以實現。
Main.exe 主程序。
Core.dll 公共接口和存貯緩存等。
T1.dll 功能1
T2.dll 功能2
現在項目有這樣的需求:
要求兩個功能之間相互調用,即T1.dll中在T1.MainForm中點擊Button1去調用T2.dll中T2.MainForm中的相應功能,反之亦然,T2.MainForm點擊Button1調用T1.dll功能。
這時就遇到了問題,直接在工程中引用dll就會出現循環引用。所以得另辟蹊徑。
解決方案:
利用反射調用dll,就避免了循環引用。不同功能間的相互通信可通過接口來解決。
具體實現:
Main.exe中用反射加載各個功能菜單,對各個Form進行實例化,緩存起來供其他功能調用。入口和實例均存在Core.MenuFactory.htMenu這個HashTable中。
再構造接口IInteraction
接口IInteraction public interface IInteraction
{
/// <summary>
/// 簡單的交互
/// </summary>
void InterAction();
/// <summary>
/// 高級交互,可傳遞參數
/// </summary>
/// <param name="args"></param>
void InterAction(object [] args);
}
T1.MainForm和T2.MainForm均繼承IInteraction。
T1.MainForm中接口實現 #region IInteraction接口實現
public void InterAction()
{
}
public void 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() private void 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(new object[] { args0, args1 });
}
}
Core.dll中加載dll的代碼如下:
T2.MainForm中接口實現參考T1.MainForm中接口實現。
T1.MainForm.Button1_Click()實現參考T2.MainForm.Button1_Click()。
總結:
通過反射解決循環引用,dll的加載都在主工程中進行,就避免了dll循環引用會導致的文件爭用問題,即解決了循環引用。
Core.ExecuteCommand.run() public static void run(string className, string assambleName)
{
Assembly assem = null;
System.Type type = null;
if (assambleName.Length == 0)
{
throw new 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
{
throw new 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();
}
新聞熱點
疑難解答