C#通過反射,創(chuàng)建窗體與控件之間的通訊,不需要引用dll,我使用的是把dll轉(zhuǎn)成內(nèi)存流直接通過反射加載到窗體中.
前提是需要知道對應的事件,或者執(zhí)行方法,廢話不多說開整
控件代碼:
public partial class UserUC : UserControl
{
private static UserUC user;//不加這一句靜態(tài)方法中沒辦法訪問自己的控件
public UserUC()
{
UserUC= this;//不加這一句靜態(tài)方法中沒辦法訪問自己的控件
InitializeComponent();
}
public delegate void 插件代理(List<string> str);
public static event 插件代理 發(fā)送消息給主窗體;
public static void 發(fā)送消息(List<string> str)
{
插件代理 handler = 發(fā)送消息給主窗體;
if (handler != null)
{
handler(str);
}
}
public static void 主窗體消息(List<string> str)
{
if (str.Count > 0)
{
var str1 = "";
foreach (var a in str)
{
str1 += a + "\n";
}
MessageBox.Show(str1, "這是一條由主窗體發(fā)來的消息");
UserUC.消息欄.Text = str1;//這里的控件由自己定義,能顯示消息就行
}
}
private void 發(fā)送消息給主窗體_Click(object sender, EventArgs e)
{
var a = new List<string>();
a.Add("這是第一條測試信息");
a.Add("這是第二條測試信息");
a.Add("這是第三條測試信息");
Plugin消息(a);
}
}
窗體代碼:
//窗體中綁定的執(zhí)行代碼
public static void MainWindowInfo(List<string> str)
{
if (str.Count > 0)
{
var str1 = "";
foreach (var a in str)
{
str1 += a + "\n";
}
MessageBox.Show(str1, "這是一條由子窗體發(fā)來的消息");
}
}
//窗體中代理和事件
public delegate void 插件推送代理(List<string> str);
public static event 插件推送代理 推送通知;
public static void 推送消息給子窗體(List<string> str)
{
插件推送代理 handler = 推送通知;
if (handler != null)
{
handler(str);
}
}
/// <summary>
/// 窗體與控件之間 委托事件互相綁定雙向通信
/// </summary>
public static UserControl ModulEventMutualCommunication(Form 當前的窗體, string 目標委托事件名稱, string 當前窗體執(zhí)行事件名稱, string 當前窗體目標委托事件名稱, string 目標綁定執(zhí)行事件名稱, MemoryStream 內(nèi)存流, List<string> 目標事件參數(shù), List<string> 自身事件參數(shù))
{
var lUc = new UserControl();
if (目標委托事件名稱 == null && 當前窗體執(zhí)行事件名稱 == null)
throw new ArgumentNullException("目標委托事件名稱錯誤");
if (當前窗體目標委托事件名稱 == null && 目標綁定執(zhí)行事件名稱 == null)
throw new ArgumentNullException("綁定執(zhí)行事件名稱錯誤");
if (內(nèi)存流 == null)
throw new ArgumentNullException("內(nèi)存流錯誤");
if (目標事件參數(shù) == null && 自身事件參數(shù) == null)
throw new ArgumentNullException("目標事件參數(shù)錯誤");
try
{
byte[] buff = 內(nèi)存流.ToArray();
Assembly assembly = Assembly.Load(buff);
Type[] type = assembly.GetTypes();
foreach (Type t in type)
{
//反射執(zhí)行的成員和類型搜索
const BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Public;
//獲取類型里面的事件信息
EventInfo eventInfo = t.GetEvent(目標委托事件名稱, myBindingFlags);
EventInfo 當前窗體eventInfo = 當前的窗體.GetType().GetEvent(當前窗體目標委托事件名稱, myBindingFlags);
//獲取到當前的類
var obj = (UserControl)assembly.CreateInstance(t.FullName);
if (eventInfo != null && 當前窗體eventInfo != null)
{
Type tDelegate = eventInfo.EventHandlerType;
Type 當前窗體Delegate = 當前窗體eventInfo.EventHandlerType;
//獲取執(zhí)行事件信息
MethodInfo methodHandler = t.GetMethod(目標綁定執(zhí)行事件名稱, myBindingFlags);
MethodInfo 當前methodHandler = 當前的窗體.GetType().GetMethod(當前窗體執(zhí)行事件名稱, myBindingFlags);
//子窗體委托給當前窗體
Delegate d = Delegate.CreateDelegate(tDelegate, 當前methodHandler);
//當前窗體委托給子窗體
Delegate dd = Delegate.CreateDelegate(當前窗體Delegate, methodHandler);
//獲取將要處理的事件委托
MethodInfo minAddHandler = eventInfo.GetAddMethod();
MethodInfo 當前窗體minAddHandler = 當前窗體eventInfo.GetAddMethod();
object[] addHandlerArgs = { d };
object[] 當前窗體addHandlerArgs = { dd };
//調(diào)用
minAddHandler.Invoke(obj, addHandlerArgs);
當前窗體minAddHandler.Invoke(當前的窗體, 當前窗體addHandlerArgs);
//集合信息
FieldInfo field = t.GetField(目標委托事件名稱, myBindingFlags);
FieldInfo 當前窗體field = 當前的窗體.GetType().GetField(當前窗體執(zhí)行事件名稱, myBindingFlags);
if (field != null && 當前窗體field != null)
{
Object fieldValue = field.GetValue(obj);
Object 當前窗體fieldValue = 當前窗體field.GetValue(當前的窗體);
if (fieldValue != null && fieldValue is Delegate)
{
Delegate objectDelegate = fieldValue as Delegate;
//動態(tài)調(diào)用
objectDelegate.DynamicInvoke(目標事件參數(shù));
Delegate 當前窗體objectDelegate = 當前窗體fieldValue as Delegate;
//動態(tài)調(diào)用
當前窗體objectDelegate.DynamicInvoke(自身事件參數(shù));
}
}
}
lUc = obj;
}
return lUc;
}
catch (FileNotFoundException)
{
MessageBox.Show("沒有找到相應的模塊", "提示!");
return lUc;
}
catch (TargetParameterCountException)
{
MessageBox.Show("調(diào)用模塊時發(fā)現(xiàn)委托的參數(shù)不同挑秉!請檢查參數(shù)的個數(shù)", "插件提示!");
return lUc;
}
catch (Exception)
{
//MessageBox.Show("插件異常提示闹获!");
return lUc;
}
調(diào)用:
var usercontrol = ModulEventMutualCommunication(this, "發(fā)送消息給主窗體", "MainWindowInfo", "推送通知", "MainView消息", ss, new List<string>() { "窗體加載成功" }, new List<string>() { "消息推送" });
usercontrol.Dock = DockStyle.Fill;
窗體容器.Controls.Add(usercontrol);