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.
596 lines
26 KiB
596 lines
26 KiB
using Microsoft.Extensions.DependencyInjection; |
|
using Newtonsoft.Json; |
|
using Newtonsoft.Json.Linq; |
|
using SqlSugar; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Linq.Expressions; |
|
using System.Reflection; |
|
using System.Text; |
|
using System.Text.RegularExpressions; |
|
using System.Threading.Tasks; |
|
using System.Diagnostics; |
|
using System.Globalization; |
|
using System.Data; |
|
|
|
namespace ReZero.SuperAPI |
|
{ |
|
public class MethodGeneratorAPI : IDataService |
|
{ |
|
private ISqlSugarClient db; |
|
public MethodGeneratorAPI() |
|
{ |
|
db = App.Db; |
|
} |
|
public async Task<object> ExecuteAction(DataModel dataModel) |
|
{ |
|
if (dataModel.MyMethodInfo == null) return null; |
|
|
|
var classType = Type.GetType(dataModel.MyMethodInfo?.MethodClassFullName); |
|
classType = GetTypeByAttribute(dataModel, classType); |
|
var methodInfo = classType.GetMyMethod(dataModel?.MyMethodInfo?.MethodName, dataModel!.MyMethodInfo!.MethodArgsCount); |
|
var classObj = ReZero.DependencyInjection.ActivatorHelper.CreateInstance(classType!, nonPublic: true, (ServiceProvider)dataModel.ServiceProvider!); |
|
object[] parameters = new object[methodInfo.GetParameters().Length]; |
|
var argsTypes = dataModel.MyMethodInfo.ArgsTypes; |
|
parameters = GetParameters(dataModel, methodInfo, parameters, argsTypes); |
|
var unitType = methodInfo.GetCustomAttributes().FirstOrDefault(it => it.GetType().GetInterfaces().Any(s => s == typeof(IUnitOfWork))); |
|
if (unitType != null) |
|
{ |
|
var unitObj =(IUnitOfWork)ReZero.DependencyInjection.ActivatorHelper.CreateInstance(unitType!.GetType(), nonPublic: true, (ServiceProvider)dataModel.ServiceProvider!); |
|
unitObj.db = ((ServiceProvider)dataModel.ServiceProvider!).GetRequiredService<ISqlSugarClient>(); |
|
try |
|
{ |
|
unitObj.BeginTran(); |
|
object result = new object(); |
|
result = await ExecuteMethodAsync(methodInfo, classObj, parameters); |
|
unitObj.CommitTran(); |
|
return result; |
|
} |
|
catch (Exception) |
|
{ |
|
unitObj.RollbackTran(); |
|
throw; |
|
} |
|
} |
|
else |
|
{ |
|
object result = await ExecuteMethodAsync(methodInfo, classObj, parameters); |
|
return result; |
|
} |
|
} |
|
|
|
private object[] GetParameters(DataModel dataModel, MethodInfo methodInfo, object[] parameters, Type[]? argsTypes) |
|
{ |
|
// 先检查method的参数类型 |
|
var methodParams = methodInfo.GetParameters(); |
|
|
|
// 先尝试判断是否是JToken/JObject参数 |
|
if (methodParams.Length == 1 && |
|
(typeof(Newtonsoft.Json.Linq.JToken).IsAssignableFrom(methodParams[0].ParameterType))) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"检测到JToken类型参数: {methodParams[0].ParameterType.Name}"); |
|
// 直接通过参数类型判断 |
|
FillJObjectDirectly(dataModel, methodParams[0].ParameterType, parameters); |
|
} |
|
else if (IsJObject(dataModel, parameters)) |
|
{ |
|
// 通过参数定义判断 |
|
FillJObjectParameters(dataModel, methodInfo, parameters, argsTypes); |
|
} |
|
else if (IsSingleModel(dataModel)) |
|
{ |
|
parameters = FillSingleModelParameters(dataModel, methodInfo); |
|
} |
|
else |
|
{ |
|
FillDefaultParameters(dataModel, methodInfo, parameters, argsTypes); |
|
} |
|
|
|
return parameters; |
|
} |
|
|
|
private static async Task<object> ExecuteMethodAsync(MethodInfo methodInfo, object classObj, object[] parameters) |
|
{ |
|
var result = methodInfo.Invoke(classObj, parameters); |
|
if (result is Task) |
|
{ |
|
result = await GetTask((Task)result); |
|
} |
|
else |
|
{ |
|
result = await Task.FromResult(result); |
|
} |
|
|
|
return result; |
|
} |
|
|
|
private static object[] FillSingleModelParameters(DataModel dataModel, MethodInfo methodInfo) |
|
{ |
|
object[] parameters; |
|
var type = methodInfo.GetParameters().First().ParameterType; |
|
var parameterOjb = Activator.CreateInstance(type, nonPublic: true); |
|
foreach (var item in type!.GetProperties()) |
|
{ |
|
// 确保属性有set方法 |
|
if (!item.CanWrite) |
|
continue; |
|
|
|
// 获取对应的参数数据 |
|
var propertyParam = dataModel.DefaultParameters.FirstOrDefault(it => it.Name == item.Name); |
|
if (propertyParam == null) |
|
continue; |
|
|
|
try |
|
{ |
|
propertyParam.Value = ConvetEmptyValue(item.PropertyType, propertyParam.Value); |
|
|
|
// 特殊处理JToken及其子类型 |
|
if (typeof(Newtonsoft.Json.Linq.JToken).IsAssignableFrom(item.PropertyType)) |
|
{ |
|
if (item.PropertyType == typeof(Newtonsoft.Json.Linq.JObject)) |
|
{ |
|
string jsonStr = propertyParam.Value?.ToString() ?? "{}"; |
|
if (jsonStr.Trim() == "null") jsonStr = "{}"; |
|
try |
|
{ |
|
item.SetValue(parameterOjb, Newtonsoft.Json.Linq.JObject.Parse(jsonStr)); |
|
} |
|
catch |
|
{ |
|
item.SetValue(parameterOjb, new Newtonsoft.Json.Linq.JObject()); |
|
} |
|
} |
|
else if (item.PropertyType == typeof(Newtonsoft.Json.Linq.JArray)) |
|
{ |
|
string jsonStr = propertyParam.Value?.ToString() ?? "[]"; |
|
if (jsonStr.Trim() == "null") jsonStr = "[]"; |
|
try |
|
{ |
|
item.SetValue(parameterOjb, Newtonsoft.Json.Linq.JArray.Parse(jsonStr)); |
|
} |
|
catch |
|
{ |
|
item.SetValue(parameterOjb, new Newtonsoft.Json.Linq.JArray()); |
|
} |
|
} |
|
else if (item.PropertyType == typeof(Newtonsoft.Json.Linq.JToken)) |
|
{ |
|
string jsonStr = propertyParam.Value?.ToString() ?? "null"; |
|
try |
|
{ |
|
item.SetValue(parameterOjb, Newtonsoft.Json.Linq.JToken.Parse(jsonStr)); |
|
} |
|
catch |
|
{ |
|
item.SetValue(parameterOjb, Newtonsoft.Json.Linq.JValue.CreateNull()); |
|
} |
|
} |
|
} |
|
else if (IsJson(item, propertyParam)) |
|
{ |
|
try |
|
{ |
|
var value = JsonConvert.DeserializeObject(propertyParam.Value + "", item.PropertyType); |
|
item.SetValue(parameterOjb, value); |
|
} |
|
catch |
|
{ |
|
// 如果JSON反序列化失败,尝试使用默认值 |
|
if (item.PropertyType.IsValueType) |
|
item.SetValue(parameterOjb, Activator.CreateInstance(item.PropertyType)); |
|
else |
|
item.SetValue(parameterOjb, null); |
|
} |
|
} |
|
else |
|
{ |
|
// 尝试使用类型转换设置值 |
|
try |
|
{ |
|
var convertedValue = UtilMethods.ChangeType2(propertyParam.Value, item.PropertyType); |
|
item.SetValue(parameterOjb, convertedValue); |
|
} |
|
catch |
|
{ |
|
// 如果类型转换失败,使用默认值 |
|
if (item.PropertyType.IsValueType) |
|
item.SetValue(parameterOjb, Activator.CreateInstance(item.PropertyType)); |
|
else |
|
item.SetValue(parameterOjb, null); |
|
} |
|
} |
|
} |
|
catch (Exception) |
|
{ |
|
// 如果设置属性值失败,继续处理下一个属性 |
|
continue; |
|
} |
|
} |
|
parameters = new object[] { parameterOjb }; |
|
return parameters; |
|
} |
|
|
|
private static bool IsJson(PropertyInfo item, DataModelDefaultParameter p) |
|
{ |
|
if (item.PropertyType?.FullName?.StartsWith("System.Collections.Generic.List")==true) |
|
{ |
|
var value2 = p.Value?.ToString()?.Trim(); |
|
return value2?.StartsWith("[") == true && value2?.EndsWith("]") == true; |
|
} |
|
if (item.PropertyType?.FullName?.StartsWith("System.")==true) |
|
{ |
|
return false; |
|
} |
|
var value = p.Value?.ToString()?.Trim(); |
|
return value?.StartsWith("{") == true && value?.EndsWith("}") == true; |
|
} |
|
|
|
private static bool IsSingleModel(DataModel dataModel) |
|
{ |
|
return dataModel.MyMethodInfo?.ArgsTypes?.Any(it => typeof(SingleModel) == it) == true; |
|
} |
|
|
|
private static Type? GetTypeByAttribute(DataModel dataModel, Type? classType) |
|
{ |
|
if (classType == null) |
|
{ |
|
var ass = SuperAPIModule._apiOptions?.DependencyInjectionOptions?.Assemblies; |
|
if (ass?.Any() == true) |
|
{ |
|
classType = ass.Select(it => it.GetType(dataModel.MyMethodInfo?.MethodClassFullName)).Where(it => it != null).FirstOrDefault(); |
|
} |
|
} |
|
return classType; |
|
} |
|
|
|
private void FillJObjectParameters(DataModel dataModel, MethodInfo methodInfo, object[] parameters, Type[]? argsTypes) |
|
{ |
|
try |
|
{ |
|
// 检查DefaultParameters是否有效 |
|
if (dataModel?.DefaultParameters == null || !dataModel.DefaultParameters.Any()) |
|
{ |
|
System.Diagnostics.Debug.WriteLine("DefaultParameters为空或null"); |
|
return; // 无法继续 |
|
} |
|
|
|
// 获取第一个参数,但使用RawJsonData而不是参数值 |
|
var rawJson = dataModel.RawJsonData; |
|
if (string.IsNullOrEmpty(rawJson)) |
|
{ |
|
// 如果RawJsonData为空,尝试从第一个参数获取值(向后兼容) |
|
var firstParam = dataModel.DefaultParameters.First(); |
|
rawJson = firstParam.Value?.ToString() ?? ""; |
|
} |
|
|
|
System.Diagnostics.Debug.WriteLine($"使用JSON数据: {rawJson}"); |
|
|
|
var type = methodInfo.GetParameters().First().ParameterType; |
|
|
|
// 处理JSON数据 |
|
if (!string.IsNullOrEmpty(rawJson)) |
|
{ |
|
try |
|
{ |
|
// 检查原始JSON是否需要转义处理 |
|
if (rawJson.Contains("\\\"")) |
|
{ |
|
rawJson = rawJson.Replace("\\\"", "\""); |
|
} |
|
|
|
// 尝试反序列化为目标类型 |
|
parameters[0] = Newtonsoft.Json.JsonConvert.DeserializeObject(rawJson, type); |
|
System.Diagnostics.Debug.WriteLine($"成功将JSON反序列化为: {type.Name}"); |
|
} |
|
catch (Exception ex) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"JSON反序列化失败: {ex.Message}"); |
|
|
|
// 如果反序列化失败,尝试其他方式 |
|
try |
|
{ |
|
if (type == typeof(Newtonsoft.Json.Linq.JObject)) |
|
{ |
|
parameters[0] = Newtonsoft.Json.Linq.JObject.Parse(rawJson); |
|
} |
|
else if (type == typeof(Newtonsoft.Json.Linq.JToken)) |
|
{ |
|
parameters[0] = Newtonsoft.Json.Linq.JToken.Parse(rawJson); |
|
} |
|
else |
|
{ |
|
// 最后尝试直接转换或使用默认值 |
|
parameters[0] = Convert.ChangeType(rawJson, type); |
|
} |
|
} |
|
catch (Exception innerEx) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"参数转换失败: {innerEx.Message}"); |
|
// 保持默认值 |
|
} |
|
} |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"FillJObjectParameters异常: {ex.Message}"); |
|
} |
|
} |
|
|
|
private static bool IsJObject(DataModel dataModel, object[] parameters) |
|
{ |
|
if (parameters.Length != 1 || dataModel.DefaultParameters.Count == 0) |
|
return false; |
|
|
|
var firstParam = dataModel.DefaultParameters.First(); |
|
|
|
// 检查是否已标记为JObject类型 |
|
bool isJObjectType = firstParam.ValueType == nameof(JObject) || |
|
firstParam.ValueType == nameof(JToken) || |
|
firstParam.ValueType == "JTokenType" || |
|
firstParam.ValueType == "Json" || |
|
firstParam.ValueType?.Contains("JObject") == true || |
|
firstParam.ValueType?.Contains("JToken") == true; |
|
|
|
// 检查是否为单个参数 |
|
bool isSingleParam = dataModel.DefaultParameters.Count == 1; |
|
|
|
// 检查JSON字符串 |
|
bool isJsonString = firstParam.Value != null && IsJsonString(firstParam.Value.ToString()); |
|
|
|
return isSingleParam && (isJObjectType || isJsonString); |
|
} |
|
|
|
private static bool IsJsonString(string value) |
|
{ |
|
if (string.IsNullOrEmpty(value)) |
|
return false; |
|
|
|
value = value.Trim(); |
|
return (value.StartsWith("{") && value.EndsWith("}")) || |
|
(value.StartsWith("[") && value.EndsWith("]")); |
|
} |
|
|
|
private static int FillDefaultParameters(DataModel dataModel, MethodInfo methodInfo, object[] parameters, Type[]? argsTypes) |
|
{ |
|
var index = 0; |
|
|
|
// 特殊处理GetToken方法,确保参数正确传递 |
|
if (methodInfo.Name == "GetToken" && dataModel.DefaultParameters?.Count == 2 && methodInfo.GetParameters().Length == 2) |
|
{ |
|
System.Diagnostics.Debug.WriteLine("检测到GetToken方法,尝试特殊处理登录参数"); |
|
|
|
// 获取用户名和密码参数 |
|
var userNameParam = dataModel.DefaultParameters.FirstOrDefault(it => it.Name?.EqualsCase("UserName") == true); |
|
var passwordParam = dataModel.DefaultParameters.FirstOrDefault(it => it.Name?.EqualsCase("Password") == true); |
|
|
|
// 检查用户名参数 |
|
if (userNameParam?.Value == null) |
|
{ |
|
// 如果找不到用户名参数值,尝试从原始JSON中提取 |
|
if (dataModel.DefaultParameters.Any(p => p.Value?.ToString()?.Contains("userName") == true || p.Value?.ToString()?.Contains("UserName") == true)) |
|
{ |
|
var jsonStr = dataModel.DefaultParameters.First(p => p.Value?.ToString()?.Contains("userName") == true || p.Value?.ToString()?.Contains("UserName") == true).Value?.ToString(); |
|
try |
|
{ |
|
var jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonStr ?? "{}"); |
|
if (jsonObj != null) |
|
{ |
|
if (jsonObj.ContainsKey("userName")) |
|
userNameParam.Value = jsonObj["userName"]; |
|
else if (jsonObj.ContainsKey("UserName")) |
|
userNameParam.Value = jsonObj["UserName"]; |
|
|
|
if (jsonObj.ContainsKey("password")) |
|
passwordParam.Value = jsonObj["password"]; |
|
else if (jsonObj.ContainsKey("Password")) |
|
passwordParam.Value = jsonObj["Password"]; |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"解析登录JSON参数失败: {ex.Message}"); |
|
} |
|
} |
|
} |
|
|
|
// 赋值参数 |
|
parameters[0] = userNameParam?.Value?.ToString() ?? ""; |
|
parameters[1] = passwordParam?.Value?.ToString() ?? ""; |
|
|
|
System.Diagnostics.Debug.WriteLine($"登录参数: UserName={parameters[0]}, Password={(parameters[1]?.ToString()?.Length > 0 ? "********" : "null")}"); |
|
return 2; |
|
} |
|
|
|
// 常规参数处理 |
|
methodInfo.GetParameters().ToList<System.Reflection.ParameterInfo>().ForEach((p) => |
|
{ |
|
object? value = dataModel?.DefaultParameters?.FirstOrDefault(it => it.Name!.EqualsCase(p.Name)).Value; |
|
if (argsTypes?.Length - 1 >= index) |
|
{ |
|
var type = argsTypes![index]; |
|
if (IsObject(value, type)) |
|
{ |
|
try |
|
{ |
|
var valueStr = value?.ToString(); |
|
if (!string.IsNullOrEmpty(valueStr)) |
|
{ |
|
value = JsonConvert.DeserializeObject(valueStr, type); |
|
} |
|
} |
|
catch (JsonException ex) |
|
{ |
|
throw new Exception(TextHandler.GetCommonText(p.Name + "JSON解析错误: " + ex.Message, |
|
p.Name + " JSON parsing error: " + ex.Message)); |
|
} |
|
} |
|
} |
|
try |
|
{ |
|
value = ConvetEmptyValue(p.ParameterType, value); |
|
value = UtilMethods.ChangeType2(value, p.ParameterType); |
|
} |
|
catch (Exception ex) |
|
{ |
|
throw new Exception(TextHandler.GetCommonText(p.Name + "参数类型不匹配 " + value + ", 错误: " + ex.Message, |
|
p.Name + " Parameter type does not match " + value + ", Error: " + ex.Message)); |
|
} |
|
parameters[p.Position] = value!; |
|
index++; |
|
}); |
|
return index; |
|
} |
|
|
|
private static object? ConvetEmptyValue(Type type, object? value) |
|
{ |
|
if (value?.Equals("") == true && type != typeof(string)) |
|
{ |
|
value = null; |
|
} |
|
|
|
// 处理JToken及其子类型 |
|
if (typeof(Newtonsoft.Json.Linq.JToken).IsAssignableFrom(type)) |
|
{ |
|
var jTokenValue = value?.ToString()?.Trim(); |
|
if (string.IsNullOrEmpty(jTokenValue)) |
|
{ |
|
// 为各种JToken类型提供默认值 |
|
if (type == typeof(Newtonsoft.Json.Linq.JObject)) |
|
return "{}"; |
|
else if (type == typeof(Newtonsoft.Json.Linq.JArray)) |
|
return "[]"; |
|
else |
|
return "null"; |
|
} |
|
return jTokenValue; |
|
} |
|
|
|
// 处理JSON数组或对象 |
|
var strValue = value?.ToString()?.Trim(); |
|
if (strValue != null) |
|
{ |
|
if ((type.IsArray || type.FullName.StartsWith("System.Collections.Generic.List")) && |
|
strValue.StartsWith("[") && strValue.EndsWith("]")) |
|
{ |
|
try |
|
{ |
|
return JsonConvert.DeserializeObject(strValue, type); |
|
} |
|
catch |
|
{ |
|
// 保持原始值 |
|
} |
|
} |
|
else if (!type.FullName.StartsWith("System.") && |
|
strValue.StartsWith("{") && strValue.EndsWith("}")) |
|
{ |
|
try |
|
{ |
|
return JsonConvert.DeserializeObject(strValue, type); |
|
} |
|
catch |
|
{ |
|
// 保持原始值 |
|
} |
|
} |
|
} |
|
|
|
return value; |
|
} |
|
private static async Task<object> GetTask(Task task) |
|
{ |
|
await task.ConfigureAwait(false); // 等待任务完成 |
|
var resultProperty = task.GetType().GetProperty("Result"); |
|
var result = resultProperty.GetValue(task); |
|
return result; |
|
} |
|
private static bool IsObject(object? value, Type type) |
|
{ |
|
if ((type.IsArray || type.FullName.StartsWith("System.Collections.Generic.List")) && value != null) |
|
{ |
|
return true; |
|
} |
|
|
|
// 检查值是否为JSON数组字符串 |
|
var valueStr = value?.ToString()?.Trim(); |
|
if (valueStr != null && valueStr.StartsWith("[") && valueStr.EndsWith("]")) |
|
{ |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
// 直接填充JObject参数,简化处理 |
|
private void FillJObjectDirectly(DataModel dataModel, Type parameterType, object[] parameters) |
|
{ |
|
try |
|
{ |
|
System.Diagnostics.Debug.WriteLine("直接填充JObject参数"); |
|
if (dataModel?.DefaultParameters == null || !dataModel.DefaultParameters.Any()) |
|
{ |
|
System.Diagnostics.Debug.WriteLine("直接填充JObject - 参数列表为空"); |
|
parameters[0] = CreateDefaultJToken(parameterType); |
|
return; |
|
} |
|
|
|
var jsonData = dataModel.DefaultParameters.First().Value?.ToString(); |
|
if (string.IsNullOrEmpty(jsonData)) |
|
{ |
|
System.Diagnostics.Debug.WriteLine("直接填充JObject - 参数值为空"); |
|
parameters[0] = CreateDefaultJToken(parameterType); |
|
return; |
|
} |
|
|
|
System.Diagnostics.Debug.WriteLine($"直接填充JObject - JSON数据: {jsonData}"); |
|
|
|
try |
|
{ |
|
// 检查是否需要处理嵌套的数据结构 |
|
if (jsonData.Contains("\"methodName\"") && jsonData.Contains("\"data\"") && |
|
parameterType == typeof(Newtonsoft.Json.Linq.JObject)) |
|
{ |
|
var jobj = Newtonsoft.Json.Linq.JObject.Parse(jsonData); |
|
// ExecuteTransaction方法直接需要整个请求对象,无需处理 |
|
parameters[0] = jobj; |
|
} |
|
else if (parameterType == typeof(Newtonsoft.Json.Linq.JObject)) |
|
{ |
|
parameters[0] = Newtonsoft.Json.Linq.JObject.Parse(jsonData); |
|
} |
|
else if (parameterType == typeof(Newtonsoft.Json.Linq.JArray)) |
|
{ |
|
parameters[0] = Newtonsoft.Json.Linq.JArray.Parse(jsonData); |
|
} |
|
else |
|
{ |
|
parameters[0] = Newtonsoft.Json.Linq.JToken.Parse(jsonData); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"直接填充JObject - 解析异常: {ex.Message}"); |
|
parameters[0] = CreateDefaultJToken(parameterType); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
System.Diagnostics.Debug.WriteLine($"直接填充JObject - 总异常: {ex.Message}"); |
|
parameters[0] = CreateDefaultJToken(parameterType); |
|
} |
|
} |
|
|
|
// 创建默认的JToken对象 |
|
private static Newtonsoft.Json.Linq.JToken CreateDefaultJToken(Type parameterType) |
|
{ |
|
if (parameterType == typeof(Newtonsoft.Json.Linq.JObject)) |
|
return new Newtonsoft.Json.Linq.JObject(); |
|
else if (parameterType == typeof(Newtonsoft.Json.Linq.JArray)) |
|
return new Newtonsoft.Json.Linq.JArray(); |
|
else |
|
return Newtonsoft.Json.Linq.JValue.CreateNull(); |
|
} |
|
} |
|
}
|
|
|