//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在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;
}
}