Framework_YooAsset_HybridCLR/Assets/Plugins/TouchSocket/TouchSocket.Rpc/Attribute/RpcAttribute.cs

997 lines
42 KiB
C#
Raw Normal View History

2024-07-16 15:16:27 +08:00
//------------------------------------------------------------------------------
// 此代码版权除特别声明或在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.Linq;
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
{
/// <summary>
/// 构造函数
/// </summary>
public RpcAttribute()
{
this.Exceptions.Add(typeof(TimeoutException), "调用超时");
this.Exceptions.Add(typeof(RpcInvokeException), "Rpc调用异常");
this.Exceptions.Add(typeof(Exception), "其他异常");
}
/// <summary>
/// 类生成器
/// </summary>
public ClassCodeGenerator ClassCodeGenerator { get; private set; }
/// <summary>
/// 异常提示
/// </summary>
public Dictionary<Type, string> Exceptions { get; } = new Dictionary<Type, string>();
/// <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>
/// 是否仅以函数名调用当为True是调用时仅需要传入方法名即可。
/// </summary>
public bool MethodInvoke { get; set; }
/// <summary>
/// 重新指定生成的函数名称。可以使用类似“JsonRpc_{0}”的模板格式。
/// </summary>
public string MethodName { get; set; }
/// <summary>
/// 获取注释信息
/// </summary>
/// <param name="rpcMethod"></param>
/// <returns></returns>
public virtual string GetDescription(RpcMethod rpcMethod)
{
return string.IsNullOrEmpty(rpcMethod.GetDescription()) ? "无注释信息" : rpcMethod.GetDescription();
}
/// <summary>
/// 获取扩展的代理代码
/// </summary>
/// <param name="rpcMethod"></param>
/// <returns></returns>
public virtual string GetExtensionsMethodProxyCode(RpcMethod rpcMethod)
{
var codeString = new StringBuilder();
var description = this.GetDescription(rpcMethod);
var parametersStr = this.GetParameters(rpcMethod, out var isOut, out var isRef, out var parameters);
var InterfaceTypes = this.GetGenericConstraintTypes();
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionSync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
codeString.Append("public static ");
codeString.Append(this.GetReturn(rpcMethod, false));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, false));
codeString.Append("<TClient>(");//方法参数
codeString.Append($"this TClient client");
codeString.Append(',');
for (var i = 0; i < parametersStr.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parametersStr[i]);
}
if (parametersStr.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(") where TClient:");
for (var i = 0; i < InterfaceTypes.Length; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(InterfaceTypes[i].FullName);
}
codeString.AppendLine("{");//方法开始
if (parametersStr.Count > 0)
{
codeString.Append($"object[] parameters = new object[]");
codeString.Append('{');
foreach (var parameter in parameters)
{
if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
{
codeString.Append($"default({this.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 (var parameter in parameters)
{
codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
if (parameter != parameters[parameters.Length - 1])
{
codeString.Append(',');
}
}
codeString.AppendLine("};");
}
}
if (rpcMethod.HasReturn)
{
if (parametersStr.Count == 0)
{
codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
else
{
if (parametersStr.Count == 0)
{
codeString.Append("client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append("client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append("client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
if (isOut || isRef)
{
codeString.AppendLine("if(parameters!=null)");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i));
}
codeString.AppendLine("}");
if (isOut)
{
codeString.AppendLine("else");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
if (parameters[i].IsOut)
{
codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i])));
}
}
codeString.AppendLine("}");
}
}
if (rpcMethod.HasReturn)
{
codeString.AppendLine("return returnData;");
}
codeString.AppendLine("}");
}
//以下生成异步
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.ExtensionAsync) /*&& !isOut && !isRef*/)
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
if (rpcMethod.HasReturn && !isOut && !isRef)
{
codeString.Append("public static async ");
}
else
{
codeString.Append("public static ");
}
codeString.Append(this.GetReturn(rpcMethod, true));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, true));
codeString.Append("<TClient>(");//方法参数
codeString.Append($"this TClient client");
codeString.Append(',');
for (var i = 0; i < parametersStr.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parametersStr[i]);
}
if (parametersStr.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(") where TClient:");
for (var i = 0; i < InterfaceTypes.Length; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(InterfaceTypes[i].FullName);
}
codeString.AppendLine("{");//方法开始
if (parametersStr.Count > 0)
{
codeString.Append($"object[] parameters = new object[]");
codeString.Append('{');
foreach (var parameter in parameters)
{
if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
{
codeString.Append($"default({this.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 (var parameter in parameters)
{
codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
if (parameter != parameters[parameters.Length - 1])
{
codeString.Append(',');
}
}
codeString.AppendLine("};");
}
}
if (rpcMethod.HasReturn)
{
if (parametersStr.Count == 0)
{
codeString.Append(string.Format("return ({0}) await client.InvokeAsync", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append(string.Format("{0} returnData=({0})client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append(string.Format("return ({0}) await client.InvokeAsync", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
else
{
if (parametersStr.Count == 0)
{
codeString.Append("return client.InvokeAsync(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append("client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append("return client.InvokeAsync(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
if (isOut || isRef)
{
codeString.AppendLine("if(parameters!=null)");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i));
}
codeString.AppendLine("}");
if (isOut)
{
codeString.AppendLine("else");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
if (parameters[i].IsOut)
{
codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i])));
}
}
codeString.AppendLine("}");
}
}
if (isOut || isRef)
{
if (rpcMethod.HasReturn)
{
codeString.AppendLine(string.Format("return Task.FromResult<{0}>(returnData);", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
}
else
{
codeString.AppendLine(string.Format("return EasyTask.CompletedTask;"));
}
}
codeString.AppendLine("}");
}
return codeString.ToString();
}
/// <summary>
/// 获取生成的函数泛型限定名称。默认<see cref="IRpcClient"/>
/// </summary>
/// <returns></returns>
public virtual Type[] GetGenericConstraintTypes()
{
return this.GenericConstraintTypes;
}
/// <summary>
/// 获取生成实体类时的代码块
/// </summary>
/// <param name="rpcMethod"></param>
/// <returns></returns>
public virtual string GetInstanceProxyCode(RpcMethod rpcMethod)
{
var codeString = new StringBuilder();
var description = this.GetDescription(rpcMethod);
var parametersStr = this.GetParameters(rpcMethod, out var isOut, out var isRef, out var parameters);
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceSync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
codeString.Append("public ");
codeString.Append(this.GetReturn(rpcMethod, false));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, false));
codeString.Append('(');//方法参数
for (var i = 0; i < parametersStr.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parametersStr[i]);
}
if (parametersStr.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(")");
codeString.AppendLine("{");//方法开始
codeString.AppendLine("if(Client==null)");
codeString.AppendLine("{");
codeString.AppendLine("throw new RpcException(\"IRpcClient为空请先初始化或者进行赋值\");");
codeString.AppendLine("}");
if (parametersStr.Count > 0)
{
codeString.Append($"object[] parameters = new object[]");
codeString.Append('{');
foreach (var parameter in parameters)
{
if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
{
codeString.Append($"default({this.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 (var parameter in parameters)
{
codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
if (parameter != parameters[parameters.Length - 1])
{
codeString.Append(',');
}
}
codeString.AppendLine("};");
}
}
if (rpcMethod.HasReturn)
{
if (parametersStr.Count == 0)
{
codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append("(");
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append("(");
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
else
{
if (parametersStr.Count == 0)
{
codeString.Append("Client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append("Client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append("Client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
if (isOut || isRef)
{
codeString.AppendLine("if(parameters!=null)");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i));
}
codeString.AppendLine("}");
if (isOut)
{
codeString.AppendLine("else");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
if (parameters[i].IsOut)
{
codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i])));
}
}
codeString.AppendLine("}");
}
}
if (rpcMethod.HasReturn)
{
codeString.AppendLine("return returnData;");
}
codeString.AppendLine("}");
}
//以下生成异步
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InstanceAsync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
if (rpcMethod.HasReturn && (!isOut && !isRef))
{
codeString.Append("public async ");
}
else
{
codeString.Append("public ");
}
codeString.Append(this.GetReturn(rpcMethod, true));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, true));
codeString.Append('(');//方法参数
for (var i = 0; i < parametersStr.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parametersStr[i]);
}
if (parametersStr.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(")");
codeString.AppendLine("{");//方法开始
codeString.AppendLine("if(Client==null)");
codeString.AppendLine("{");
codeString.AppendLine("throw new RpcException(\"IRpcClient为空请先初始化或者进行赋值\");");
codeString.AppendLine("}");
if (parametersStr.Count > 0)
{
codeString.Append($"object[] parameters = new object[]");
codeString.Append('{');
foreach (var parameter in parameters)
{
if (parameter.ParameterType.Name.Contains("&") && parameter.IsOut)
{
codeString.Append($"default({this.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 (var parameter in parameters)
{
codeString.Append($"typeof({this.GetProxyParameterName(parameter)})");
if (parameter != parameters[parameters.Length - 1])
{
codeString.Append(',');
}
}
codeString.AppendLine("};");
}
}
if (rpcMethod.HasReturn)
{
if (parametersStr.Count == 0)
{
codeString.Append(string.Format("return ({0}) await Client.InvokeAsync", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append(string.Format("{0} returnData=({0})Client.Invoke", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append(string.Format("return ({0}) await Client.InvokeAsync", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append('(');
codeString.Append(string.Format("typeof({0}),", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
else
{
if (parametersStr.Count == 0)
{
codeString.Append("return Client.InvokeAsync(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, null);");
}
else if (isOut || isRef)
{
codeString.Append("Client.Invoke(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption,ref parameters,types);");
}
else
{
codeString.Append("return Client.InvokeAsync(");
codeString.Append($"\"{this.GetInvokenKey(rpcMethod)}\"");
codeString.AppendLine(",invokeOption, parameters);");
}
}
if (isOut || isRef)
{
codeString.AppendLine("if(parameters!=null)");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
codeString.AppendLine(string.Format("{0}=({1})parameters[{2}];", parameters[i].Name, this.GetProxyParameterName(parameters[i]), i));
}
codeString.AppendLine("}");
if (isOut)
{
codeString.AppendLine("else");
codeString.AppendLine("{");
for (var i = 0; i < parameters.Length; i++)
{
if (parameters[i].IsOut)
{
codeString.AppendLine(string.Format("{0}=default({1});", parameters[i].Name, this.GetProxyParameterName(parameters[i])));
}
}
codeString.AppendLine("}");
}
}
if (isOut || isRef)
{
if (rpcMethod.HasReturn)
{
codeString.AppendLine(string.Format("return Task.FromResult<{0}>(returnData);", this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)));
}
else
{
codeString.AppendLine(string.Format("return EasyTask.CompletedTask;"));
}
}
codeString.AppendLine("}");
}
return codeString.ToString();
}
/// <summary>
/// 获取接口的代理代码
/// </summary>
/// <param name="rpcMethod"></param>
/// <returns></returns>
public virtual string GetInterfaceProxyCode(RpcMethod rpcMethod)
{
var codeString = new StringBuilder();
var description = this.GetDescription(rpcMethod);
var parameters = this.GetParameters(rpcMethod, out var isOut, out var isRef, out _);
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceSync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
codeString.Append(this.GetReturn(rpcMethod, false));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, false));
codeString.Append('(');//方法参数
for (var i = 0; i < parameters.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parameters[i]);
}
if (parameters.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(");");
}
if (this.GeneratorFlag.HasFlag(CodeGeneratorFlag.InterfaceAsync))
{
codeString.AppendLine("///<summary>");
codeString.AppendLine($"///{description}");
codeString.AppendLine("///</summary>");
foreach (var item in this.Exceptions)
{
codeString.AppendLine($"/// <exception cref=\"{item.Key.FullName}\">{item.Value}</exception>");
}
codeString.Append(this.GetReturn(rpcMethod, true));
codeString.Append(' ');
codeString.Append(this.GetMethodName(rpcMethod, true));
codeString.Append('(');//方法参数
for (var i = 0; i < parameters.Count; i++)
{
if (i > 0)
{
codeString.Append(',');
}
codeString.Append(parameters[i]);
}
if (parameters.Count > 0)
{
codeString.Append(',');
}
codeString.Append(this.GetInvokeOption());
codeString.AppendLine(");");
}
return codeString.ToString();
}
/// <summary>
/// 获取调用键
/// </summary>
/// <param name="rpcMethod"></param>
/// <returns></returns>
public virtual string GetInvokenKey(RpcMethod rpcMethod)
{
if (this.MethodInvoke)
{
return this.GetMethodName(rpcMethod, false);
}
else
{
return !this.InvokeKey.IsNullOrEmpty() ? this.InvokeKey : $"{rpcMethod.ServerFromType.FullName}.{rpcMethod.Name}".ToLower();
}
}
/// <summary>
/// 获取调用配置
/// </summary>
/// <returns></returns>
public virtual string GetInvokeOption()
{
return "IInvokeOption invokeOption = default";
}
/// <summary>
/// 获取生成的函数名称
/// </summary>
/// <param name="rpcMethod"></param>
/// <param name="isAsync"></param>
/// <returns></returns>
public virtual string GetMethodName(RpcMethod rpcMethod, bool isAsync)
{
var name = string.IsNullOrEmpty(this.MethodName) ? rpcMethod.Name : this.MethodName.Format(rpcMethod.Name);
return isAsync ? name + "Async" : name;
}
/// <summary>
/// 获取参数生成
/// </summary>
/// <param name="rpcMethod"></param>
/// <param name="isOut"></param>
/// <param name="isRef"></param>
/// <param name="parameters"></param>
/// <returns></returns>
public virtual List<string> GetParameters(RpcMethod rpcMethod, out bool isOut, out bool isRef, out ParameterInfo[] parameters)
{
var list = new List<string>();
isOut = false;
isRef = false;
parameters = rpcMethod.GetNormalParameters().Select(a => a.ParameterInfo).ToArray();
for (var i = 0; i < parameters.Length; i++)
{
var codeString = new StringBuilder();
if (parameters[i].ParameterType.Name.Contains("&"))
{
if (parameters[i].IsOut)
{
isOut = true;
codeString.Append(string.Format("out {0} {1}", this.GetProxyParameterName(parameters[i]), parameters[i].Name));
}
else
{
isRef = true;
codeString.Append(string.Format("ref {0} {1}", this.GetProxyParameterName(parameters[i]), parameters[i].Name));
}
}
else
{
codeString.Append(string.Format("{0} {1}", this.GetProxyParameterName(parameters[i]), parameters[i].Name));
}
if (parameters[i].HasDefaultValue)
{
var 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 this.ClassCodeGenerator.GetTypeFullName(parameterInfo);
}
/// <summary>
/// 获取返回值
/// </summary>
/// <param name="rpcMethod"></param>
/// <param name="isAsync"></param>
/// <returns></returns>
public virtual string GetReturn(RpcMethod rpcMethod, bool isAsync)
{
if (isAsync)
{
return rpcMethod.ReturnType == null ? "Task" : $"Task<{this.GetProxyParameterName(rpcMethod.Info.ReturnParameter)}>";
}
else
{
return rpcMethod.ReturnType == null ? "void" : this.GetProxyParameterName(rpcMethod.Info.ReturnParameter);
}
}
internal void SetClassCodeGenerator(ClassCodeGenerator classCodeGenerator)
{
this.ClassCodeGenerator = classCodeGenerator;
}
}
}