//------------------------------------------------------------------------------
// 此代码版权(除特别声明或在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.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using TouchSocket.Core;
namespace TouchSocket.Rpc
{
///
/// 代码生成器
///
public static class CodeGenerator
{
internal static readonly List m_assemblies = new List();
internal static readonly List m_ignoreAssemblies = new List();
internal static readonly List m_ignoreTypes = new List();
internal static readonly Dictionary m_proxyType = new Dictionary();
private const BindingFlags m_methodFlags = BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public;
///
/// 添加不需要代理的程序集
///
///
public static void AddIgnoreProxyAssembly(Assembly assembly)
{
m_ignoreAssemblies.Add(assembly);
}
///
/// 添加不需要代理的类型
///
///
public static void AddIgnoreProxyType(Type type)
{
m_ignoreTypes.Add(type);
}
///
/// 添加需要代理的程序集
///
///
public static void AddProxyAssembly(Assembly assembly)
{
m_assemblies.Add(assembly);
}
///
/// 添加代理类型
///
///
///
public static void AddProxyType(Type type, bool deepSearch = true)
{
if (type.IsPrimitive || type == typeof(string))
{
return;
}
if (!m_proxyType.ContainsKey(type))
{
RpcProxyAttribute attribute = type.GetCustomAttribute();
m_proxyType.Add(type, attribute == null ? type.Name : attribute.ClassName);
if (deepSearch)
{
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty);
foreach (var item in properties)
{
AddProxyType(item.PropertyType);
}
}
}
}
///
/// 添加代理类型
///
///
///
public static void AddProxyType(bool deepSearch = true)
{
AddProxyType(typeof(T), deepSearch);
}
///
/// 是否包含类型
///
///
///
public static bool ContainsType(Type type)
{
return m_proxyType.ContainsKey(type);
}
///
/// 转换为cs代码。
///
///
///
///
public static string ConvertToCode(string @namespace, params ServerCellCode[] serverCodes)
{
Dictionary serverCellCodes = new Dictionary();
Dictionary classCellCodes = new Dictionary();
StringBuilder codeString = new StringBuilder();
foreach (var serverCellCode in serverCodes)
{
if (serverCellCodes.ContainsKey(serverCellCode.Name))
{
if (serverCellCode.IncludeExtension)
{
serverCellCodes[serverCellCode.Name].IncludeExtension = true;
}
if (serverCellCode.IncludeInstance)
{
serverCellCodes[serverCellCode.Name].IncludeInstance = true;
}
if (serverCellCode.IncludeInterface)
{
serverCellCodes[serverCellCode.Name].IncludeInterface = true;
}
var ccm = serverCellCodes[serverCellCode.Name].Methods;
foreach (var item in serverCellCode.Methods.Keys)
{
if (!ccm.ContainsKey(item))
{
ccm.Add(item, serverCellCode.Methods[item]);
}
}
}
else
{
serverCellCodes.Add(serverCellCode.Name, serverCellCode);
}
foreach (var item in serverCellCode.ClassCellCodes.Keys)
{
if (!classCellCodes.ContainsKey(item))
{
classCellCodes.Add(item, serverCellCode.ClassCellCodes[item]);
}
}
}
string namesp = string.IsNullOrEmpty(@namespace) ? "RRQMProxy" : @namespace;
codeString.AppendLine("using System;");
codeString.AppendLine("using TouchSocket.Core;");
codeString.AppendLine("using TouchSocket.Sockets;");
codeString.AppendLine("using TouchSocket.Rpc;");
codeString.AppendLine("using TouchSocket.Rpc.TouchRpc;");
codeString.AppendLine("using System.Collections.Generic;");
codeString.AppendLine("using System.Diagnostics;");
codeString.AppendLine("using System.Text;");
codeString.AppendLine("using System.Threading.Tasks;");
codeString.AppendLine(string.Format("namespace {0}", namesp));
codeString.AppendLine("{");
foreach (var serverCellCode in serverCellCodes.Values)
{
if (serverCellCode.IncludeInterface)
{
//接口
codeString.AppendLine($"public interface I{serverCellCode.Name}:{typeof(IRemoteServer).FullName}");//类开始
codeString.AppendLine("{");
foreach (var item in serverCellCode.Methods.Values)
{
codeString.AppendLine(item.InterfaceTemple);
}
codeString.AppendLine("}");
//接口
}
if (serverCellCode.IncludeInstance)
{
//类
if (serverCellCode.IncludeInterface)
{
codeString.AppendLine($"public class {serverCellCode.Name} :I{serverCellCode.Name}");//类开始
}
else
{
codeString.AppendLine($"public class {serverCellCode.Name}");//类开始
}
codeString.AppendLine("{");
codeString.AppendLine($"public {serverCellCode.Name}(IRpcClient client)");
codeString.AppendLine("{");
codeString.AppendLine("this.Client=client;");
codeString.AppendLine("}");
codeString.AppendLine("public IRpcClient Client{get;private set; }");
foreach (var item in serverCellCode.Methods.Values)
{
codeString.AppendLine(item.CodeTemple);
}
codeString.AppendLine("}");
//类
}
if (serverCellCode.IncludeExtension)
{
//扩展类
codeString.AppendLine($"public static class {serverCellCode.Name}Extensions");//类开始
codeString.AppendLine("{");
foreach (var item in serverCellCode.Methods.Values)
{
codeString.AppendLine(item.ExtensionsTemple);
}
codeString.AppendLine("}");
//扩展类
}
}
foreach (var item in classCellCodes.Values)
{
codeString.AppendLine(item.Code);
}
codeString.AppendLine("}");
return codeString.ToString();
}
///
/// 生成代码代理
///
/// 服务类型
/// 属性标签
///
public static ServerCellCode Generator() where TServer : IRpcServer where TAttribute : RpcAttribute
{
return Generator(typeof(TServer), typeof(TAttribute));
}
///
/// 生成代码代理
///
/// 服务类型
///
///
public static ServerCellCode Generator(Type serverType, Type attributeType)
{
ServerCellCode serverCellCode = new ServerCellCode();
MethodInstance[] methodInstances = GetMethodInstances(serverType, serverType);
List assemblies = new List(m_assemblies);
assemblies.Add(serverType.Assembly);
foreach (var item in m_ignoreAssemblies)
{
assemblies.Remove(item);
}
ClassCodeGenerator classCodeGenerator = new ClassCodeGenerator(assemblies.ToArray());
serverCellCode.Name = serverType.IsInterface ?
(serverType.Name.StartsWith("I") ? serverType.Name.Remove(0, 1) : serverType.Name) : serverType.Name;
List instances = new List();
foreach (var item in m_proxyType.Keys)
{
int deep = 0;
classCodeGenerator.AddTypeString(item, ref deep);
}
foreach (MethodInstance methodInstance in methodInstances)
{
foreach (RpcAttribute att in methodInstance.RpcAttributes)
{
if (attributeType == att.GetType())
{
if (methodInstance.ReturnType != null)
{
int deep = 0;
classCodeGenerator.AddTypeString(methodInstance.ReturnType, ref deep);
}
int i = 0;
if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
{
i = 1;
}
for (; i < methodInstance.ParameterTypes.Length; i++)
{
int deep = 0;
classCodeGenerator.AddTypeString(methodInstance.ParameterTypes[i], ref deep);
}
instances.Add(methodInstance);
break;
}
}
}
classCodeGenerator.CheckDeep();
//foreach (var item in classCodeGenerator.GenericTypeDic.Keys.ToArray())
//{
// if (m_ignoreTypes.Contains(item))
// {
// classCodeGenerator.GenericTypeDic.TryRemove(item, out _);
// }
// if (m_ignoreAssemblies.Contains(item.Assembly))
// {
// classCodeGenerator.GenericTypeDic.TryRemove(item, out _);
// }
//}
foreach (var item in classCodeGenerator.PropertyDic.Keys.ToArray())
{
if (m_ignoreTypes.Contains(item))
{
classCodeGenerator.PropertyDic.TryRemove(item, out _);
}
if (m_ignoreAssemblies.Contains(item.Assembly))
{
classCodeGenerator.PropertyDic.TryRemove(item, out _);
}
}
foreach (var item in classCodeGenerator.GetClassCellCodes())
{
serverCellCode.ClassCellCodes.Add(item.Name, item);
}
//ServerCodeGenerator serverCodeGenerator = new ServerCodeGenerator(classCodeGenerator);
bool first = true;
foreach (var item in instances)
{
MethodCellCode methodCellCode = new MethodCellCode();
RpcAttribute rpcAttribute = (RpcAttribute)item.GetAttribute(attributeType);
if (rpcAttribute == null)
{
continue;
}
rpcAttribute.SetClassCodeGenerator(classCodeGenerator);
if (first)
{
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync) || rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceSync))
{
serverCellCode.IncludeInterface = true;
}
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync) || rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceSync))
{
serverCellCode.IncludeInstance = true;
}
if (rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) || rpcAttribute.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionSync))
{
serverCellCode.IncludeExtension = true;
}
first = false;
}
methodCellCode.InterfaceTemple = rpcAttribute.GetInterfaceProxyCode(item);
methodCellCode.CodeTemple = rpcAttribute.GetInstanceProxyCode(item);
methodCellCode.ExtensionsTemple = rpcAttribute.GetExtensionsMethodProxyCode(item);
methodCellCode.Name = ((RpcAttribute)item.GetAttribute(attributeType)).GetMethodName(item, false);
serverCellCode.Methods.Add(methodCellCode.Name, methodCellCode);
}
return serverCellCode;
}
///
/// 从类型获取函数实例
///
///
///
public static MethodInstance[] GetMethodInstances() where TServer : IRpcServer
{
return GetMethodInstances(typeof(TServer), typeof(TServer));
}
///
/// 从类型获取函数实例
///
///
///
///
public static MethodInstance[] GetMethodInstances(Type serverFromType, Type serverToType)
{
if (!typeof(IRpcServer).IsAssignableFrom(serverFromType))
{
throw new RpcException($"服务类型必须从{nameof(IRpcServer)}派生。");
}
if (!serverFromType.IsAssignableFrom(serverToType))
{
throw new RpcException($"{serverToType}类型必须从{serverFromType}派生。");
}
List instances = new List();
var fromMethodInfos = new Dictionary();
GetMethodInfos(serverFromType, ref fromMethodInfos);
var toMethodInfos = new Dictionary();
GetMethodInfos(serverToType, ref toMethodInfos);
foreach (MethodInfo method in fromMethodInfos.Values)
{
if (method.IsGenericMethod)
{
continue;
}
IEnumerable attributes = method.GetCustomAttributes(true);
if (attributes.Count() > 0)
{
MethodInstance methodInstance = new MethodInstance(method)
{
ServerType = serverFromType,
IsEnable = true,
Parameters = method.GetParameters()
};
if (!toMethodInfos.TryGetValue(GetMethodID(method), out var toMethod))
{
throw new InvalidOperationException($"没有找到方法{method.Name}的实现");
}
List actionFilters = new List();
foreach (var item in method.GetCustomAttributes(true))
{
if (item is IRpcActionFilter filter)
{
actionFilters.Add(filter);
}
}
if (serverFromType!=serverToType)
{
foreach (var item in toMethod.GetCustomAttributes(true))
{
if (item is IRpcActionFilter filter)
{
actionFilters.Add(filter);
}
}
}
if (actionFilters.Count > 0)
{
methodInstance.Filters = actionFilters.ToArray();
}
foreach (var item in attributes)
{
methodInstance.MethodFlags |= item.MethodFlags;
}
if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
{
if (methodInstance.Parameters.Length == 0 || !typeof(ICallContext).IsAssignableFrom(methodInstance.Parameters[0].ParameterType))
{
throw new RpcException($"函数:{method},标识包含{MethodFlags.IncludeCallContext}时,必须包含{nameof(ICallContext)}或其派生类参数,且为第一参数。");
}
}
List names = new List();
foreach (var parameterInfo in methodInstance.Parameters)
{
names.Add(parameterInfo.Name);
}
methodInstance.ParameterNames = names.ToArray();
ParameterInfo[] parameters = method.GetParameters();
List types = new List();
foreach (var parameter in parameters)
{
types.Add(parameter.ParameterType.GetRefOutType());
}
methodInstance.ParameterTypes = types.ToArray();
instances.Add(methodInstance);
}
}
return instances.ToArray();
}
///
/// 生成代理代码
///
///
///
///
///
public static string GetProxyCodes(string @namespace, Type[] serverTypes, Type[] attributeTypes)
{
List serverCellCodeList = new List();
foreach (var item in serverTypes)
{
foreach (var item1 in attributeTypes)
{
serverCellCodeList.Add(Generator(item, item1));
}
}
return ConvertToCode(@namespace, serverCellCodeList.ToArray());
}
///
/// 获取类型代理名称
///
///
///
///
public static bool TryGetProxyTypeName(Type type, out string className)
{
return m_proxyType.TryGetValue(type, out className);
}
private static string GetMethodID(MethodInfo method)
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append(method.Name);
foreach (var item in method.GetParameters())
{
stringBuilder.Append(item.ParameterType.FullName);
}
return stringBuilder.ToString();
}
private static void GetMethodInfos(Type type, ref Dictionary infos)
{
if (type.IsInterface)
{
foreach (var item in type.GetInterfaces())
{
GetMethodInfos(item, ref infos);
}
}
foreach (var item in type.GetMethods(m_methodFlags))
{
if (!infos.ContainsKey(GetMethodID(item)))
{
infos.Add(GetMethodID(item), item);
}
}
}
}
}