You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
902 lines
36 KiB
902 lines
36 KiB
|
3 months ago
|
//------------------------------------------------------------------------------
|
||
|
|
// 此代码版权(除特别声明或在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.Reflection;
|
||
|
|
using System.Text;
|
||
|
|
using TouchSocket.Core;
|
||
|
|
|
||
|
|
namespace TouchSocket.Rpc
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// Rpc方法属性基类
|
||
|
|
/// </summary>
|
||
|
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
|
||
|
|
public abstract class RpcAttribute : Attribute
|
||
|
|
{
|
||
|
|
private readonly Dictionary<Type, string> m_exceptions = new Dictionary<Type, string>();
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 构造函数
|
||
|
|
/// </summary>
|
||
|
|
public RpcAttribute()
|
||
|
|
{
|
||
|
|
MethodFlags = MethodFlags.None;
|
||
|
|
m_exceptions.Add(typeof(TimeoutException), "调用超时");
|
||
|
|
m_exceptions.Add(typeof(RpcInvokeException), "Rpc调用异常");
|
||
|
|
m_exceptions.Add(typeof(Exception), "其他异常");
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 类生成器
|
||
|
|
/// </summary>
|
||
|
|
public ClassCodeGenerator ClassCodeGenerator { get; private set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 异常提示
|
||
|
|
/// </summary>
|
||
|
|
public Dictionary<Type, string> Exceptions => m_exceptions;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 生成代码
|
||
|
|
/// </summary>
|
||
|
|
public CodeGeneratorFlag GeneratorFlag { get; set; } =
|
||
|
|
CodeGeneratorFlag.InstanceSync | CodeGeneratorFlag.InstanceAsync | CodeGeneratorFlag.ExtensionSync | CodeGeneratorFlag.ExtensionAsync
|
||
|
|
| CodeGeneratorFlag.InterfaceSync | CodeGeneratorFlag.InterfaceAsync;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 生成泛型方法的约束
|
||
|
|
/// </summary>
|
||
|
|
public Type[] GenericConstraintTypes { get; set; } = new Type[] { typeof(IRpcClient) };
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 调用键。
|
||
|
|
/// </summary>
|
||
|
|
public string InvokeKey { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 函数标识
|
||
|
|
/// </summary>
|
||
|
|
public MethodFlags MethodFlags { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 是否仅以函数名调用,当为True是,调用时仅需要传入方法名即可。
|
||
|
|
/// </summary>
|
||
|
|
public bool MethodInvoke { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 重新指定生成的函数名称。可以使用类似“JsonRpc_{0}”的模板格式。
|
||
|
|
/// </summary>
|
||
|
|
public string MethodName { get; set; }
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 当使用TryCanInvoke不能调用时,执行的代码。
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetCannotInvoke(MethodInstance methodInstance)
|
||
|
|
{
|
||
|
|
return "throw new RpcException(\"Rpc无法执行。\");";
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取注释信息
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetDescription(MethodInstance methodInstance)
|
||
|
|
{
|
||
|
|
return string.IsNullOrEmpty(methodInstance.GetDescription()) ? "无注释信息" : methodInstance.GetDescription();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取扩展的代理代码
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetExtensionsMethodProxyCode(MethodInstance methodInstance)
|
||
|
|
{
|
||
|
|
StringBuilder codeString = new StringBuilder();
|
||
|
|
|
||
|
|
string description = GetDescription(methodInstance);
|
||
|
|
|
||
|
|
List<string> parametersStr = GetParameters(methodInstance, out bool isOut, out bool isRef, out ParameterInfo[] parameters);
|
||
|
|
var InterfaceTypes = GetGenericConstraintTypes();
|
||
|
|
if (GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionSync))
|
||
|
|
{
|
||
|
|
codeString.AppendLine("///<summary>");
|
||
|
|
codeString.AppendLine($"///{description}");
|
||
|
|
codeString.AppendLine("///</summary>");
|
||
|
|
foreach (var item in Exceptions)
|
||
|
|
{
|
||
|
|
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append("public static ");
|
||
|
|
codeString.Append(GetReturn(methodInstance, false));
|
||
|
|
codeString.Append(" ");
|
||
|
|
codeString.Append(GetMethodName(methodInstance, false));
|
||
|
|
codeString.Append("<TClient>(");//方法参数
|
||
|
|
|
||
|
|
codeString.Append($"this TClient client");
|
||
|
|
|
||
|
|
codeString.Append(",");
|
||
|
|
for (int i = 0; i < parametersStr.Count; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append(parametersStr[i]);
|
||
|
|
}
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(GetInvokeOption());
|
||
|
|
codeString.AppendLine(") where TClient:");
|
||
|
|
|
||
|
|
for (int i = 0; i < InterfaceTypes.Length; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append(InterfaceTypes[i].FullName);
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.AppendLine("{");//方法开始
|
||
|
|
|
||
|
|
codeString.AppendLine("if (client.TryCanInvoke?.Invoke(client)==false)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
codeString.AppendLine(GetCannotInvoke(methodInstance));
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append($"object[] parameters = new object[]");
|
||
|
|
codeString.Append("{");
|
||
|
|
|
||
|
|
foreach (ParameterInfo parameter in parameters)
|
||
|
|
{
|
||
|
|
if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
|
||
|
|
{
|
||
|
|
codeString.Append($"default({GetProxyParameterName(parameter)})");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(parameter.Name);
|
||
|
|
}
|
||
|
|
if (parameter != parameters[parameters.Length - 1])
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("};");
|
||
|
|
|
||
|
|
if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.Append($"Type[] types = new Type[]");
|
||
|
|
codeString.Append("{");
|
||
|
|
foreach (ParameterInfo parameter in parameters)
|
||
|
|
{
|
||
|
|
codeString.Append($"typeof({GetProxyParameterName(parameter)})");
|
||
|
|
if (parameter != parameters[parameters.Length - 1])
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("};");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (methodInstance.HasReturn)
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} returnData=client.Invoke<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} returnData=client.Invoke<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption,ref parameters,types);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} returnData=client.Invoke<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append("client.Invoke(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.Append("client.Invoke(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption,ref parameters,types);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append("client.Invoke(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.AppendLine("if(parameters!=null)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
|
{
|
||
|
|
codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, GetProxyParameterName(parameters[i]), i));
|
||
|
|
}
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
if (isOut)
|
||
|
|
{
|
||
|
|
codeString.AppendLine("else");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
|
{
|
||
|
|
if (parameters[i].IsOut)
|
||
|
|
{
|
||
|
|
codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, GetProxyParameterName(parameters[i])));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (methodInstance.HasReturn)
|
||
|
|
{
|
||
|
|
codeString.AppendLine("return returnData;");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
}
|
||
|
|
|
||
|
|
//以下生成异步
|
||
|
|
if (GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) && !isOut && !isRef)//没有out或者ref
|
||
|
|
{
|
||
|
|
codeString.AppendLine("///<summary>");
|
||
|
|
codeString.AppendLine($"///{description}");
|
||
|
|
codeString.AppendLine("///</summary>");
|
||
|
|
codeString.Append("public static ");
|
||
|
|
codeString.Append(GetReturn(methodInstance, true));
|
||
|
|
codeString.Append(" ");
|
||
|
|
codeString.Append(GetMethodName(methodInstance, true));
|
||
|
|
codeString.Append("<TClient>(");//方法参数
|
||
|
|
|
||
|
|
codeString.Append($"this TClient client");
|
||
|
|
|
||
|
|
codeString.Append(",");
|
||
|
|
for (int i = 0; i < parametersStr.Count; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(parametersStr[i]);
|
||
|
|
}
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(GetInvokeOption());
|
||
|
|
codeString.AppendLine(") where TClient:");
|
||
|
|
|
||
|
|
for (int i = 0; i < InterfaceTypes.Length; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append(InterfaceTypes[i].FullName);
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.AppendLine("{");//方法开始
|
||
|
|
|
||
|
|
codeString.AppendLine("if (client.TryCanInvoke?.Invoke(client)==false)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
codeString.AppendLine($"throw new RpcException(\"Rpc无法执行。\");");
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append($"object[] parameters = new object[]");
|
||
|
|
codeString.Append("{");
|
||
|
|
foreach (ParameterInfo parameter in parameters)
|
||
|
|
{
|
||
|
|
codeString.Append(parameter.Name);
|
||
|
|
if (parameter != parameters[parameters.Length - 1])
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("};");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (methodInstance.HasReturn)
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("return client.InvokeAsync<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("return client.InvokeAsync<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append("return client.InvokeAsync(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append("return client.InvokeAsync(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
}
|
||
|
|
return codeString.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取生成的函数泛型限定名称。默认<see cref="IRpcClient"/>
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual Type[] GetGenericConstraintTypes()
|
||
|
|
{
|
||
|
|
return GenericConstraintTypes;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取生成实体类时的代码块
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetInstanceProxyCode(MethodInstance methodInstance)
|
||
|
|
{
|
||
|
|
StringBuilder codeString = new StringBuilder();
|
||
|
|
|
||
|
|
string description = GetDescription(methodInstance);
|
||
|
|
ParameterInfo[] parameters;
|
||
|
|
bool isOut;
|
||
|
|
bool isRef;
|
||
|
|
List<string> parametersStr = GetParameters(methodInstance, out isOut, out isRef, out parameters);
|
||
|
|
if (GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceSync))
|
||
|
|
{
|
||
|
|
codeString.AppendLine("///<summary>");
|
||
|
|
codeString.AppendLine($"///{description}");
|
||
|
|
codeString.AppendLine("///</summary>");
|
||
|
|
foreach (var item in Exceptions)
|
||
|
|
{
|
||
|
|
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append("public ");
|
||
|
|
codeString.Append(GetReturn(methodInstance, false));
|
||
|
|
codeString.Append(" ");
|
||
|
|
codeString.Append(GetMethodName(methodInstance, false));
|
||
|
|
codeString.Append("(");//方法参数
|
||
|
|
|
||
|
|
for (int i = 0; i < parametersStr.Count; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(parametersStr[i]);
|
||
|
|
}
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(GetInvokeOption());
|
||
|
|
codeString.AppendLine(")");
|
||
|
|
|
||
|
|
codeString.AppendLine("{");//方法开始
|
||
|
|
|
||
|
|
codeString.AppendLine("if(Client==null)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
codeString.AppendLine("throw new RpcException(\"IRpcClient为空,请先初始化或者进行赋值\");");
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
codeString.AppendLine("if (Client.TryCanInvoke?.Invoke(Client)==false)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
codeString.AppendLine($"throw new RpcException(\"Rpc无法执行。\");");
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append($"object[] parameters = new object[]");
|
||
|
|
codeString.Append("{");
|
||
|
|
|
||
|
|
foreach (ParameterInfo parameter in parameters)
|
||
|
|
{
|
||
|
|
if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
|
||
|
|
{
|
||
|
|
codeString.Append($"default({GetProxyParameterName(parameter)})");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(parameter.Name);
|
||
|
|
}
|
||
|
|
if (parameter != parameters[parameters.Length - 1])
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("};");
|
||
|
|
|
||
|
|
if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.Append($"Type[] types = new Type[]");
|
||
|
|
codeString.Append("{");
|
||
|
|
foreach (ParameterInfo parameter in parameters)
|
||
|
|
{
|
||
|
|
codeString.Append($"typeof({GetProxyParameterName(parameter)})");
|
||
|
|
if (parameter != parameters[parameters.Length - 1])
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("};");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (methodInstance.HasReturn)
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} returnData=Client.Invoke<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} returnData=Client.Invoke<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption,ref parameters,types);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} returnData=Client.Invoke<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append("Client.Invoke(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.Append("Client.Invoke(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption,ref parameters,types);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append("Client.Invoke(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (isOut || isRef)
|
||
|
|
{
|
||
|
|
codeString.AppendLine("if(parameters!=null)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
|
{
|
||
|
|
codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, GetProxyParameterName(parameters[i]), i));
|
||
|
|
}
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
if (isOut)
|
||
|
|
{
|
||
|
|
codeString.AppendLine("else");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
|
{
|
||
|
|
if (parameters[i].IsOut)
|
||
|
|
{
|
||
|
|
codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, GetProxyParameterName(parameters[i])));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (methodInstance.HasReturn)
|
||
|
|
{
|
||
|
|
codeString.AppendLine("return returnData;");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
}
|
||
|
|
|
||
|
|
//以下生成异步
|
||
|
|
if (GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync) && !isOut && !isRef)//没有out或者ref
|
||
|
|
{
|
||
|
|
codeString.AppendLine("///<summary>");
|
||
|
|
codeString.AppendLine($"///{description}");
|
||
|
|
codeString.AppendLine("///</summary>");
|
||
|
|
codeString.Append("public ");
|
||
|
|
codeString.Append(GetReturn(methodInstance, true));
|
||
|
|
codeString.Append(" ");
|
||
|
|
codeString.Append(GetMethodName(methodInstance, true));
|
||
|
|
codeString.Append("(");//方法参数
|
||
|
|
|
||
|
|
for (int i = 0; i < parametersStr.Count; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(parametersStr[i]);
|
||
|
|
}
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(GetInvokeOption());
|
||
|
|
codeString.AppendLine(")");
|
||
|
|
|
||
|
|
codeString.AppendLine("{");//方法开始
|
||
|
|
|
||
|
|
codeString.AppendLine("if(Client==null)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
codeString.AppendLine("throw new RpcException(\"IRpcClient为空,请先初始化或者进行赋值\");");
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
|
||
|
|
codeString.AppendLine("if (Client.TryCanInvoke?.Invoke(Client)==false)");
|
||
|
|
codeString.AppendLine("{");
|
||
|
|
codeString.AppendLine($"throw new RpcException(\"Rpc无法执行。\");");
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
|
||
|
|
if (parametersStr.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append($"object[] parameters = new object[]");
|
||
|
|
codeString.Append("{");
|
||
|
|
foreach (ParameterInfo parameter in parameters)
|
||
|
|
{
|
||
|
|
codeString.Append(parameter.Name);
|
||
|
|
if (parameter != parameters[parameters.Length - 1])
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("};");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (methodInstance.HasReturn)
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("return Client.InvokeAsync<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("return Client.InvokeAsync<{0}>", GetProxyParameterName(methodInstance.Info.ReturnParameter)));
|
||
|
|
codeString.Append("(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (parametersStr.Count == 0)
|
||
|
|
{
|
||
|
|
codeString.Append("return Client.InvokeAsync(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, null);");
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append("return Client.InvokeAsync(");
|
||
|
|
codeString.Append($"\"{GetInvokenKey(methodInstance)}\"");
|
||
|
|
codeString.AppendLine(",invokeOption, parameters);");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
codeString.AppendLine("}");
|
||
|
|
}
|
||
|
|
return codeString.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取接口的代理代码
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetInterfaceProxyCode(MethodInstance methodInstance)
|
||
|
|
{
|
||
|
|
StringBuilder codeString = new StringBuilder();
|
||
|
|
bool isOut = false;
|
||
|
|
bool isRef = false;
|
||
|
|
string description = GetDescription(methodInstance);
|
||
|
|
List<string> parameters = GetParameters(methodInstance, out isOut, out isRef, out _);
|
||
|
|
if (GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceSync))
|
||
|
|
{
|
||
|
|
codeString.AppendLine("///<summary>");
|
||
|
|
codeString.AppendLine($"///{description}");
|
||
|
|
codeString.AppendLine("///</summary>");
|
||
|
|
foreach (var item in Exceptions)
|
||
|
|
{
|
||
|
|
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append(GetReturn(methodInstance, false));
|
||
|
|
codeString.Append(" ");
|
||
|
|
codeString.Append(GetMethodName(methodInstance, false));
|
||
|
|
codeString.Append("(");//方法参数
|
||
|
|
for (int i = 0; i < parameters.Count; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(parameters[i]);
|
||
|
|
}
|
||
|
|
if (parameters.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(GetInvokeOption());
|
||
|
|
codeString.AppendLine(");");
|
||
|
|
}
|
||
|
|
|
||
|
|
if (GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync) && !isOut && !isRef)//没有out或者ref
|
||
|
|
{
|
||
|
|
codeString.AppendLine("///<summary>");
|
||
|
|
codeString.AppendLine($"///{description}");
|
||
|
|
codeString.AppendLine("///</summary>");
|
||
|
|
foreach (var item in Exceptions)
|
||
|
|
{
|
||
|
|
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
|
||
|
|
}
|
||
|
|
|
||
|
|
codeString.Append(GetReturn(methodInstance, true));
|
||
|
|
codeString.Append(" ");
|
||
|
|
codeString.Append(GetMethodName(methodInstance, true));
|
||
|
|
codeString.Append("(");//方法参数
|
||
|
|
|
||
|
|
for (int i = 0; i < parameters.Count; i++)
|
||
|
|
{
|
||
|
|
if (i > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(parameters[i]);
|
||
|
|
}
|
||
|
|
if (parameters.Count > 0)
|
||
|
|
{
|
||
|
|
codeString.Append(",");
|
||
|
|
}
|
||
|
|
codeString.Append(GetInvokeOption());
|
||
|
|
codeString.AppendLine(");");
|
||
|
|
}
|
||
|
|
|
||
|
|
return codeString.ToString();
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取调用键
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetInvokenKey(MethodInstance methodInstance)
|
||
|
|
{
|
||
|
|
if (MethodInvoke)
|
||
|
|
{
|
||
|
|
return GetMethodName(methodInstance, false);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!InvokeKey.IsNullOrEmpty())
|
||
|
|
{
|
||
|
|
return InvokeKey;
|
||
|
|
}
|
||
|
|
return $"{methodInstance.ServerType.FullName}.{methodInstance.Name}".ToLower();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取调用配置
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetInvokeOption()
|
||
|
|
{
|
||
|
|
return "IInvokeOption invokeOption = default";
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取生成的函数名称
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <param name="isAsync"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetMethodName(MethodInstance methodInstance, bool isAsync)
|
||
|
|
{
|
||
|
|
string name;
|
||
|
|
if (string.IsNullOrEmpty(MethodName))
|
||
|
|
{
|
||
|
|
name = methodInstance.Name;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
name = MethodName.Format(methodInstance.Name);
|
||
|
|
}
|
||
|
|
return isAsync ? name + "Async" : name;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取参数生成
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <param name="isOut"></param>
|
||
|
|
/// <param name="isRef"></param>
|
||
|
|
/// <param name="parameters"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual List<string> GetParameters(MethodInstance methodInstance, out bool isOut, out bool isRef, out ParameterInfo[] parameters)
|
||
|
|
{
|
||
|
|
List<string> list = new List<string>();
|
||
|
|
isOut = false;
|
||
|
|
isRef = false;
|
||
|
|
|
||
|
|
if (methodInstance.MethodFlags.HasFlag(MethodFlags.IncludeCallContext))
|
||
|
|
{
|
||
|
|
List<ParameterInfo> infos = new List<ParameterInfo>(methodInstance.Parameters);
|
||
|
|
infos.RemoveAt(0);
|
||
|
|
parameters = infos.ToArray();
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
parameters = methodInstance.Parameters;
|
||
|
|
}
|
||
|
|
|
||
|
|
for (int i = 0; i < parameters.Length; i++)
|
||
|
|
{
|
||
|
|
StringBuilder codeString = new StringBuilder();
|
||
|
|
if (parameters[i].ParameterType.Name.Contains("&"))
|
||
|
|
{
|
||
|
|
if (parameters[i].IsOut)
|
||
|
|
{
|
||
|
|
isOut = true;
|
||
|
|
codeString.Append(string.Format("out {0} {1}", GetProxyParameterName(parameters[i]), parameters[i].Name));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
isRef = true;
|
||
|
|
codeString.Append(string.Format("ref {0} {1}", GetProxyParameterName(parameters[i]), parameters[i].Name));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("{0} {1}", GetProxyParameterName(parameters[i]), parameters[i].Name));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (parameters[i].HasDefaultValue)
|
||
|
|
{
|
||
|
|
object defaultValue = parameters[i].DefaultValue;
|
||
|
|
if (defaultValue == null)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("=null"));
|
||
|
|
}
|
||
|
|
else if (defaultValue.ToString() == string.Empty)
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("=\"\""));
|
||
|
|
}
|
||
|
|
else if (defaultValue.GetType() == typeof(string))
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("=\"{0}\"", defaultValue));
|
||
|
|
}
|
||
|
|
else if (defaultValue.GetType() == typeof(bool))
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("={0}", defaultValue.ToString().ToLower()));
|
||
|
|
}
|
||
|
|
else if (typeof(ValueType).IsAssignableFrom(defaultValue.GetType()))
|
||
|
|
{
|
||
|
|
codeString.Append(string.Format("={0}", defaultValue));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
list.Add(codeString.ToString());
|
||
|
|
}
|
||
|
|
|
||
|
|
return list;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 从类型获取代理名
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="parameterInfo"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetProxyParameterName(ParameterInfo parameterInfo)
|
||
|
|
{
|
||
|
|
return ClassCodeGenerator.GetTypeFullName(parameterInfo);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取返回值
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="methodInstance"></param>
|
||
|
|
/// <param name="isAsync"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public virtual string GetReturn(MethodInstance methodInstance, bool isAsync)
|
||
|
|
{
|
||
|
|
if (isAsync)
|
||
|
|
{
|
||
|
|
if (methodInstance.ReturnType == null)
|
||
|
|
{
|
||
|
|
return "Task";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return $"Task<{GetProxyParameterName(methodInstance.Info.ReturnParameter)}>";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (methodInstance.ReturnType == null)
|
||
|
|
{
|
||
|
|
return "void";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return GetProxyParameterName(methodInstance.Info.ReturnParameter);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal void SetClassCodeGenerator(ClassCodeGenerator classCodeGenerator)
|
||
|
|
{
|
||
|
|
ClassCodeGenerator = classCodeGenerator;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|