//------------------------------------------------------------------------------ // 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有 // 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权 // CSDN博客:https://blog.csdn.net/qq_40374647 // 哔哩哔哩视频:https://space.bilibili.com/94253567 // Gitee源代码仓库:https://gitee.com/RRQM_Home // Github源代码仓库:https://github.com/RRQM // API首页:https://www.yuque.com/rrqm/touchsocket/index // 交流QQ群:234762506 // 感谢您的下载和使用 //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; namespace TouchSocket.Core { /// /// 表示插件管理器。 /// public class PluginsManager : IPluginsManager { private readonly Dictionary> m_pluginInfoes = new Dictionary>(); private readonly List m_plugins = new List(); /// /// 构造函数 /// /// public PluginsManager(IContainer container) { Container = container; } /// /// /// public IContainer Container { get; } /// /// /// public bool Enable { get; set; } = true; /// /// 添加插件 /// /// 插件 /// void IPluginsManager.Add(IPlugin plugin) { lock (this) { if (plugin == null) { throw new ArgumentNullException(); } if (plugin.GetType().GetCustomAttribute() is SingletonPluginAttribute singletonPlugin) { foreach (var item in m_plugins) { if (item.PluginType == plugin.GetType()) { throw new InvalidOperationException($"插件{plugin.GetType()}不能重复使用。"); } } } m_plugins.Add(new PluginModel(plugin, plugin.GetType())); var types = plugin.GetType().GetInterfaces().Where(a => typeof(IPlugin).IsAssignableFrom(a)).ToArray(); foreach (var type in types) { if (!m_pluginInfoes.ContainsKey(type)) { Dictionary pairs = new Dictionary(); var ms = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (var item in ms) { if (item.GetParameters().Length == 2 && typeof(TouchSocketEventArgs).IsAssignableFrom(item.GetParameters()[1].ParameterType)) { if (pairs.ContainsKey(item.Name)) { throw new Exception("插件的接口方法不允许重载"); } PluginMethod pluginMethod = new PluginMethod(type); if (item.GetCustomAttribute() != null) { var asyncMethod = type.GetMethod($"{item.Name}Async", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); if (asyncMethod == null) { throw new Exception("当接口标识为异步时,还应当定义其异步方法,以“Async”结尾"); } if (asyncMethod.GetParameters().Length != 2 && typeof(TouchSocketEventArgs).IsAssignableFrom(asyncMethod.GetParameters()[1].ParameterType)) { throw new Exception("异步接口方法不符合设定"); } if (asyncMethod.ReturnType != typeof(Task)) { throw new Exception("异步接口方法返回值必须为Task。"); } pluginMethod.MethodAsync=new Method(asyncMethod); } pluginMethod.Method = new Method(item); pairs.Add(item.Name, pluginMethod); } } m_pluginInfoes.Add(type, pairs); } } m_plugins.Sort(delegate (PluginModel x, PluginModel y) { if (x.Plugin.Order == y.Plugin.Order) return 0; else if (x.Plugin.Order < y.Plugin.Order) return 1; else return -1; }); Container.RegisterSingleton(plugin); } } /// /// 清除所有插件 /// void IPluginsManager.Clear() { lock (this) { foreach (var item in m_plugins) { item.Plugin.SafeDispose(); } m_plugins.Clear(); } } IEnumerator IEnumerable.GetEnumerator() { lock (this) { return m_plugins.Select(a => a.Plugin).GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { lock (this) { return m_plugins.Select(a => a.Plugin).GetEnumerator(); } } /// /// 触发对应方法 /// /// 接口类型,此处也必须是接口类型 /// 触发名称 /// /// bool IPluginsManager.Raise(string name, object sender, TouchSocketEventArgs e) { if (!Enable) { return false; } if (m_pluginInfoes.TryGetValue(typeof(TPlugin), out var value)) { if (value.TryGetValue(name, out PluginMethod pluginMethod)) { for (int i = 0; i < m_plugins.Count; i++) { if (e.Handled) { return true; } if (pluginMethod.Type.IsAssignableFrom(m_plugins[i].PluginType)) { try { pluginMethod.Method.Invoke(m_plugins[i].Plugin, sender, e); } catch (Exception ex) { Container.Resolve()?.Exception(ex); } try { pluginMethod.MethodAsync?.InvokeAsync(m_plugins[i].Plugin, sender, e); } catch (Exception ex) { Container.Resolve()?.Exception(ex); } } } } } return false; } /// /// 移除插件 /// /// void IPluginsManager.Remove(IPlugin plugin) { lock (this) { if (plugin == null) { throw new ArgumentNullException(); } foreach (var item in m_plugins) { if (plugin == item.Plugin) { if (m_plugins.Remove(item)) { plugin.SafeDispose(); return; } } } } } /// /// 移除插件 /// /// void IPluginsManager.Remove(Type type) { lock (this) { for (int i = m_plugins.Count - 1; i >= 0; i--) { IPlugin plugin = m_plugins[i].Plugin; if (plugin.GetType() == type) { m_plugins.RemoveAt(i); plugin.SafeDispose(); } } } } } internal class PluginMethod { public PluginMethod(Type type) { this.Type = type; } public Method Method; public Method MethodAsync; public readonly Type Type; } internal class PluginModel { public PluginModel(IPlugin plugin, Type pluginType) { Plugin = plugin; PluginType = pluginType; } public IPlugin Plugin; public Type PluginType; } }