330 lines
11 KiB
C#
330 lines
11 KiB
C#
|
//------------------------------------------------------------------------------
|
|||
|
// 此代码版权(除特别声明或在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://touchsocket.net/
|
|||
|
// 交流QQ群:234762506
|
|||
|
// 感谢您的下载和使用
|
|||
|
//------------------------------------------------------------------------------
|
|||
|
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Linq;
|
|||
|
using System.Reflection;
|
|||
|
using TouchSocket.Core;
|
|||
|
|
|||
|
namespace TouchSocket.Rpc
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Rpc函数实例
|
|||
|
/// </summary>
|
|||
|
public sealed class RpcMethod : Method
|
|||
|
{
|
|||
|
private readonly bool[] m_hasFilters = new bool[4];
|
|||
|
private RpcAttribute[] m_rpcAttributes;
|
|||
|
private RpcAttribute[] m_serverRpcAttributes;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 实例化一个Rpc调用函数,并在方法声明的类上操作
|
|||
|
/// </summary>
|
|||
|
/// <param name="methodInfo"></param>
|
|||
|
public RpcMethod(MethodInfo methodInfo) : this(methodInfo, methodInfo.DeclaringType, methodInfo.DeclaringType)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 实例化一个Rpc调用函数,并在指定类上操作
|
|||
|
/// </summary>
|
|||
|
/// <param name="method"></param>
|
|||
|
/// <param name="serverFromType"></param>
|
|||
|
/// <param name="serverToType"></param>
|
|||
|
public RpcMethod(MethodInfo method, Type serverFromType, Type serverToType) : base(method, false)
|
|||
|
{
|
|||
|
this.ServerFromType = serverFromType;
|
|||
|
this.ServerToType = serverToType;
|
|||
|
|
|||
|
this.Parameters = method.GetParameters().Select(a => new RpcParameter(a)).ToArray();
|
|||
|
|
|||
|
var name = $"{serverToType.Name}{method.Name}Func";
|
|||
|
var property = serverToType.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Static);
|
|||
|
if (property == null)
|
|||
|
{
|
|||
|
if (GlobalEnvironment.DynamicBuilderType == DynamicBuilderType.IL)
|
|||
|
{
|
|||
|
this.m_invoker = this.CreateILInvoker(method);
|
|||
|
}
|
|||
|
else if (GlobalEnvironment.DynamicBuilderType == DynamicBuilderType.Expression)
|
|||
|
{
|
|||
|
this.m_invoker = this.CreateExpressionInvoker(method);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.m_invoker = (Func<object, object[], object>)property.GetValue(null);
|
|||
|
}
|
|||
|
|
|||
|
var fromMethodInfos = new Dictionary<string, MethodInfo>();
|
|||
|
CodeGenerator.GetMethodInfos(this.ServerFromType, ref fromMethodInfos);
|
|||
|
|
|||
|
var toMethodInfos = new Dictionary<string, MethodInfo>();
|
|||
|
CodeGenerator.GetMethodInfos(this.ServerToType, ref toMethodInfos);
|
|||
|
|
|||
|
var attributes = method.GetCustomAttributes<RpcAttribute>(true);
|
|||
|
if (attributes.Any())
|
|||
|
{
|
|||
|
if (!toMethodInfos.TryGetValue(CodeGenerator.GetMethodId(method), out var toMethod))
|
|||
|
{
|
|||
|
throw new InvalidOperationException($"没有找到方法{method.Name}的实现");
|
|||
|
}
|
|||
|
this.ToMethodInfo = toMethod;
|
|||
|
|
|||
|
this.ParameterNames = this.Parameters.Select(a => a.Name).ToArray();
|
|||
|
this.ParameterTypes = this.Parameters.Select(a => a.Type).ToArray();
|
|||
|
}
|
|||
|
|
|||
|
this.PrivateGetFilters();
|
|||
|
|
|||
|
if (typeof(ITransientRpcServer).IsAssignableFrom(this.ServerToType))
|
|||
|
{
|
|||
|
this.HasCallContext = true;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.HasCallContext = this.Parameters.Where(a => a.IsCallContext).Any();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否可用
|
|||
|
/// </summary>
|
|||
|
public bool IsEnable { get; set; } = true;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 参数名集合
|
|||
|
/// </summary>
|
|||
|
public string[] ParameterNames { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 参数集合
|
|||
|
/// </summary>
|
|||
|
public RpcParameter[] Parameters { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 参数类型集合,已处理out及ref,无参数时为空集合,
|
|||
|
/// </summary>
|
|||
|
public Type[] ParameterTypes { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否包含调用上下文
|
|||
|
/// </summary>
|
|||
|
public bool HasCallContext { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取常规Rpc参数。
|
|||
|
/// </summary>
|
|||
|
/// <returns></returns>
|
|||
|
public IEnumerable<RpcParameter> GetNormalParameters()
|
|||
|
{
|
|||
|
return this.Parameters.Where(a =>
|
|||
|
{
|
|||
|
if (a.IsFromServices)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (a.IsCallContext)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
if (a.Type.IsInterface)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Rpc属性集合
|
|||
|
/// </summary>
|
|||
|
public RpcAttribute[] RpcAttributes
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
this.m_rpcAttributes ??= this.Info.GetCustomAttributes<RpcAttribute>(true).ToArray();
|
|||
|
return this.m_rpcAttributes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 注册类型
|
|||
|
/// </summary>
|
|||
|
public Type ServerFromType { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Rpc服务属性集合
|
|||
|
/// </summary>
|
|||
|
public RpcAttribute[] ServerRpcAttributes
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
this.m_serverRpcAttributes ??= this.ServerFromType.GetCustomAttributes<RpcAttribute>(true).ToArray();
|
|||
|
return this.m_serverRpcAttributes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 实例类型
|
|||
|
/// </summary>
|
|||
|
public Type ServerToType { get; private set; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 实现方法。
|
|||
|
/// </summary>
|
|||
|
public MethodInfo ToMethodInfo { get; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取指定类型属性标签
|
|||
|
/// </summary>
|
|||
|
/// <typeparam name="T"></typeparam>
|
|||
|
/// <returns></returns>
|
|||
|
public T GetAttribute<T>()
|
|||
|
{
|
|||
|
var attribute = this.GetAttribute(typeof(T));
|
|||
|
return attribute != null ? (T)attribute : default;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 获取指定类型属性标签
|
|||
|
/// </summary>
|
|||
|
/// <param name="attributeType"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public object GetAttribute(Type attributeType)
|
|||
|
{
|
|||
|
object attribute = this.RpcAttributes.FirstOrDefault((a) => { return attributeType.IsAssignableFrom(a.GetType()); });
|
|||
|
if (attribute != null)
|
|||
|
{
|
|||
|
return attribute;
|
|||
|
}
|
|||
|
|
|||
|
attribute = this.ServerRpcAttributes.FirstOrDefault((a) => { return attributeType.IsAssignableFrom(a.GetType()); });
|
|||
|
return attribute ?? default;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 描述属性
|
|||
|
/// </summary>
|
|||
|
public string GetDescription()
|
|||
|
{
|
|||
|
return this.Info.GetCustomAttribute<DescriptionAttribute>()?.Description;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 筛选器
|
|||
|
/// </summary>
|
|||
|
public IList<IRpcActionFilter> GetFilters()
|
|||
|
{
|
|||
|
if (this.m_hasFilters[0] || this.m_hasFilters[1] || this.m_hasFilters[2] || this.m_hasFilters[3])
|
|||
|
{
|
|||
|
var actionFilters = new List<IRpcActionFilter>();
|
|||
|
//注册方法
|
|||
|
if (this.m_hasFilters[0])
|
|||
|
{
|
|||
|
foreach (var item in this.Info.GetCustomAttributes(typeof(IRpcActionFilter), false))
|
|||
|
{
|
|||
|
this.m_hasFilters[0] = true;
|
|||
|
this.AddActionFilter((IRpcActionFilter)item, ref actionFilters);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (this.m_hasFilters[1])
|
|||
|
{
|
|||
|
//实现方法
|
|||
|
if (this.ServerFromType != this.ServerToType)
|
|||
|
{
|
|||
|
foreach (var item in this.ToMethodInfo.GetCustomAttributes(typeof(IRpcActionFilter), false))
|
|||
|
{
|
|||
|
this.m_hasFilters[1] = true;
|
|||
|
this.AddActionFilter((IRpcActionFilter)item, ref actionFilters);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (this.m_hasFilters[2])
|
|||
|
{
|
|||
|
//注册类
|
|||
|
foreach (var item in this.ServerFromType.GetCustomAttributes(typeof(IRpcActionFilter), false))
|
|||
|
{
|
|||
|
this.m_hasFilters[2] = true;
|
|||
|
this.AddActionFilter((IRpcActionFilter)item, ref actionFilters);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (this.m_hasFilters[3])
|
|||
|
{
|
|||
|
//实现类
|
|||
|
if (this.ServerFromType != this.ServerToType)
|
|||
|
{
|
|||
|
foreach (var item in this.ServerToType.GetCustomAttributes(typeof(IRpcActionFilter), false))
|
|||
|
{
|
|||
|
this.m_hasFilters[3] = true;
|
|||
|
this.AddActionFilter((IRpcActionFilter)item, ref actionFilters);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return actionFilters;
|
|||
|
}
|
|||
|
return new IRpcActionFilter[0];
|
|||
|
}
|
|||
|
|
|||
|
private void AddActionFilter(IRpcActionFilter filter, ref List<IRpcActionFilter> filters)
|
|||
|
{
|
|||
|
foreach (var item in filters)
|
|||
|
{
|
|||
|
if (item.GetType() == filter.GetType())
|
|||
|
{
|
|||
|
//同一类型
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
foreach (var item2 in item.MutexAccessTypes)
|
|||
|
{
|
|||
|
if (item2.IsAssignableFrom(filter.GetType()))
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
filters.Add(filter);
|
|||
|
}
|
|||
|
|
|||
|
private void PrivateGetFilters()
|
|||
|
{
|
|||
|
//注册方法
|
|||
|
this.m_hasFilters[0] = this.Info.GetCustomAttributes(typeof(IRpcActionFilter), false).Any();
|
|||
|
|
|||
|
//实现方法
|
|||
|
if (this.ServerFromType != this.ServerToType)
|
|||
|
{
|
|||
|
this.m_hasFilters[1] = this.ToMethodInfo.GetCustomAttributes(typeof(IRpcActionFilter), false).Any();
|
|||
|
}
|
|||
|
|
|||
|
//注册类
|
|||
|
this.m_hasFilters[2] = this.ServerFromType.GetCustomAttributes(typeof(IRpcActionFilter), false).Any();
|
|||
|
|
|||
|
//实现类
|
|||
|
if (this.ServerFromType != this.ServerToType)
|
|||
|
{
|
|||
|
this.m_hasFilters[3] = this.ServerToType.GetCustomAttributes(typeof(IRpcActionFilter), false).Any();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|