在插件式开发。我们要调用其它插件或模块的委托事件时、那么我们需要通过反射。
Module 模块
namespace Module2 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> [Plugin("MainWindow", "测试反射")] public partial class MainWindow { public delegate void TestHandler(string msg,string info,string text); public event TestHandler TestEvent; public MainWindow() { InitializeComponent(); } protected virtual void ValueInformation(string text, string info, string tb) { TestHandler handler = TestEvent; if (handler != null) handler(text,info,tb); } private void button1_Click(object sender, RoutedEventArgs e) { if (TestEvent != null) { } ValueInformation("你好!钓鱼岛是中国的!!","打死小日本!!",textBox1.Text); } public override void UninstallEvent() { //添加已经打开的窗口 :在关闭的时候 要删除此项 ApplicationSharedData.LoadedPlugins.Remove("Module2.MainWindow"); base.UninstallEvent(); } } }
反射
1 /// <summary> 2 /// 模块之间 委托事件 通信 3 /// </summary> 4 /// <param name="currentWindow">当前的Window</param> 5 /// <param name="reflectioneventName">要反射模块中的 委托事件名称</param> 6 /// <param name="currentEventName">在当前类中要执行的事件名称</param> 7 /// <param name="filePath">反射文件的路经</param> 8 /// <param name="plugin">插件</param> 9 /// <param name="eventParameter">通信的消息</param> 10 public static void ModulEventCommunication(Window currentWindow, string reflectioneventName, 11 string currentEventName, string filePath, Plugin plugin, 12 object[] eventParameter) 13 { 14 if (reflectioneventName == null) 15 throw new ArgumentNullException("reflectioneventName"); 16 if (currentEventName == null) 17 throw new ArgumentNullException("currentEventName"); 18 if (filePath == null) 19 throw new ArgumentNullException("filePath"); 20 if (eventParameter == null) 21 throw new ArgumentNullException("eventParameter"); 22 try 23 { 24 Assembly assembly = Assembly.LoadFrom(filePath + plugin.NameSpace + "." + plugin.Exends); 25 Type[] type = assembly.GetTypes(); 26 foreach (Type t in type) 27 { 28 //主要是判断该窗口是否实现 IElementsView 如果没有实现 就不需要反射或者不是插件 29 if (t.GetInterface("IElementsView") != null && t.Name == plugin.ClassName) 30 { 31 //注:在这里要判断是否已经加载: 32 if (LoadedPlugins.Contains(t.FullName)) 33 { 34 return; 35 } 36 //反射执行的成员和类型搜索 37 const BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static; 38 EventInfo eventInfo = t.GetEvent(reflectioneventName, myBindingFlags); 39 //获取到当前的类 40 var obj = (IElementsView)assembly.CreateInstance(t.FullName); 41 if (eventInfo != null) 42 { 43 Type tDelegate = eventInfo.EventHandlerType; 44 MethodInfo methodHandler = currentWindow.GetType().GetMethod(currentEventName,myBindingFlags); 45 //创建委托 46 Delegate d = Delegate.CreateDelegate(tDelegate, methodHandler); 47 //获取将要处理的事件委托 48 MethodInfo minAddHandler = eventInfo.GetAddMethod(); 49 object[] addHandlerArgs = { d }; 50 //调用 51 minAddHandler.Invoke(obj, addHandlerArgs); 52 FieldInfo field = t.GetField(reflectioneventName, 53 myBindingFlags); 54 if (field != null) 55 { 56 Object fieldValue = field.GetValue(obj); 57 if (fieldValue != null && fieldValue is Delegate) 58 { 59 Delegate objectDelegate = fieldValue as Delegate; 60 //动态调用 61 objectDelegate.DynamicInvoke(eventParameter); 62 } 63 } 64 } 65 if (obj != null) 66 { 67 obj.ShowWindow(); 68 //添加已经打开的窗口 :在关闭的时候 要删除此项 69 LoadedPlugins.Add(t.FullName); 70 } 71 } 72 73 } 74 } 75 catch (FileNotFoundException) 76 { 77 MessageBox.Show("尊敬的用户您好!没有找到相应的模块!", "插件提示!", MessageBoxButton.OK, 78 MessageBoxImage.Information); 79 } 80 catch (TargetParameterCountException) 81 { 82 MessageBox.Show("尊敬的用户您好!在调用模块时发现委托的参数不同!请检查参数的个数!", "插件提示!", MessageBoxButton.OK, 83 MessageBoxImage.Information); 84 } 85 catch (Exception) 86 { 87 MessageBox.Show("尊敬的用户您好!系统发现版本与当前系统不匹配!", "插件提示!", MessageBoxButton.OK, 88 MessageBoxImage.Information); 89 } 90 }
本模块调用:
调用反射信息
void Test2_Click(object sender, RoutedEventArgs e) { var item = (MenuItem)sender; string path = @Environment.CurrentDirectory + "\\"; Plugin plugin = ApplicationSharedData.Plugins[item.Header.ToString()]; ApplicationSharedData.ModulEventCommunication(this, "TestEvent", "DeleBindData", path, plugin, new object[] { "参数1", "参数2","" }); //注 在反射TestEvent 时候 ,TestEvent有几个参数 那么S_TestEvent 也有几个参数。 //不然会抛出异常信息,TargetParameterCountException 参数的个数不同 } private static void DeleBindData(string msg, string info,string tb) { _textbox.Text = tb; }
此代码是我在一次开发中遇到的问题。。在这里做个备注 ,防止下次忘记了。。