在Serein.Library添加了基础功能模块,暂时实现了键值对/数组数据的创建(可配合JSON库进行序列化)

This commit is contained in:
fengjiayi
2024-11-04 23:30:52 +08:00
parent b7be0f2c6e
commit dff9a00fb6
33 changed files with 1046 additions and 609 deletions

View File

@@ -31,6 +31,11 @@ namespace Serein.Library.Api
/// </summary>
ConnectionInvokeType NextOrientation { get; set; }
/// <summary>
/// 运行时异常信息
/// </summary>
Exception ExceptionOfRuning { get; set; }
/// <summary>
/// 设置节点的运行时上一节点,用以多线程中隔开不同流程的数据
/// </summary>

View File

@@ -857,18 +857,20 @@ namespace Serein.Library.Api
/// <summary>
/// 获取方法描述信息
/// </summary>
/// <param name="assemblyName">程序集名称</param>
/// <param name="methodName">方法描述</param>
/// <param name="mdInfo">方法信息</param>
/// <returns></returns>
bool TryGetMethodDetailsInfo(string libraryName, string methodName, out MethodDetailsInfo mdInfo);
bool TryGetMethodDetailsInfo(string assemblyName, string methodName, out MethodDetailsInfo mdInfo);
/// <summary>
/// 获取指定方法的Emit委托
/// </summary>
/// <param name="assemblyName">程序集名称</param>
/// <param name="methodName"></param>
/// <param name="del"></param>
/// <returns></returns>
bool TryGetDelegateDetails(string libraryName, string methodName, out DelegateDetails del);
bool TryGetDelegateDetails(string assemblyName, string methodName, out DelegateDetails del);
#region

View File

@@ -26,6 +26,7 @@ namespace Serein.Library
_emitDelegate = emitDelegate;
}
/// <summary>
/// 记录Emit委托
/// </summary>
@@ -36,7 +37,9 @@ namespace Serein.Library
_emitMethodType = EmitMethodType;
_emitDelegate = EmitDelegate;
}
/// <summary>
/*/// <summary>
/// 更新委托方法
/// </summary>
/// <param name="EmitMethodType"></param>
@@ -45,7 +48,9 @@ namespace Serein.Library
{
_emitMethodType = EmitMethodType;
_emitDelegate = EmitDelegate;
}
}*/
private Delegate _emitDelegate;
private EmitMethodType _emitMethodType;

View File

@@ -1,6 +1,7 @@
using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -36,7 +37,7 @@ namespace Serein.Library
private bool _isProtectionParameter;
/// <summary>
/// 作用实例的类型(多个相同的节点将拥有相同的类型)
/// 调用节点方法时需要的实例(多个相同的节点将拥有相同的类型)
/// </summary>
[PropertyInfo]
private Type _actingInstanceType;
@@ -77,6 +78,7 @@ namespace Serein.Library
/// </summary>
[PropertyInfo]
private ParameterDetails[] _parameterDetailss;
//private List<ParameterDetails> _parameterDetailss;
/// <summary>
/// <para>描述该方法是否存在可选参数</para>
@@ -137,6 +139,9 @@ namespace Serein.Library
&& index < ParameterDetailss.Length) // 防止下标越界
{
ParameterDetailss[index] = null; // 释放对象引用
var tmp = ArrayHelper.RemoteToArray<ParameterDetails>(ParameterDetailss, index); // 新增;
UpdateParamIndex(ref tmp);
ParameterDetailss = tmp; // 新增

View File

@@ -62,25 +62,6 @@ namespace Serein.Library
/// </summary>
[PropertyInfo(IsProtection = true)]
private MethodDetails _methodDetails ;
/// <summary>
/// 运行时的上一节点
/// </summary>
//[PropertyInfo]
//private NodeModelBase _previousNode ;
/// <summary>
/// 当前节点执行完毕后需要执行的下一个分支的类别
/// </summary>
//[PropertyInfo]
//private ConnectionInvokeType _nextOrientation = ConnectionInvokeType.None;
/// <summary>
/// 运行时的异常信息(仅在 FlowState 为 Error 时存在对应值)
/// </summary>
[PropertyInfo]
private Exception _runingException ;
}

View File

@@ -11,6 +11,7 @@ using System.Linq;
using System.Linq.Expressions;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -109,7 +110,7 @@ namespace Serein.Library
{
// 保存的参数信息项数量大于方法本身的方法入参数量(可能存在可变入参)
var length = nodeInfo.ParameterData.Length - pds.Length; // 需要扩容的长度
this.MethodDetails.ParameterDetailss = ArrayHelper.ArrayExpansion(pds, length); // 扩容入参描述数组
this.MethodDetails.ParameterDetailss = ArrayHelper.Expansion(pds, length); // 扩容入参描述数组
pds = this.MethodDetails.ParameterDetailss;
var startParmsPd = pds[md.ParamsArgIndex]; // 获取可变入参参数描述
for(int i = md.ParamsArgIndex + 1; i <= md.ParamsArgIndex + length; i++)
@@ -144,6 +145,10 @@ namespace Serein.Library
}
#endregion
#region
#endregion
#region
/// <summary>
@@ -256,7 +261,6 @@ namespace Serein.Library
newFlowData = null;
await Console.Out.WriteLineAsync($"节点[{this.MethodDetails?.MethodName}]异常:" + ex);
context.NextOrientation = ConnectionInvokeType.IsError;
currentNode.RuningException = ex;
}
@@ -317,7 +321,7 @@ namespace Serein.Library
{
throw new Exception($"节点{this.Guid}不存在方法信息请检查是否需要重写节点的ExecutingAsync");
}
if (!context.Env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd))
if (!context.Env.TryGetDelegateDetails(md.AssemblyName, md.MethodName, out var dd)) // 流程运行到某个节点
{
throw new Exception($"节点{this.Guid}不存在对应委托");
}
@@ -700,4 +704,68 @@ namespace Serein.Library
#endregion
}
#if false
public static class NodeModelExtension
{
/// <summary>
/// 程序集更新,更新节点方法描述、以及所有入参描述的类型
/// </summary>
/// <param name="nodeModel">节点Model</param>
/// <param name="newMd">新的方法描述</param>
public static void UploadMethod(this NodeModelBase nodeModel, MethodDetails newMd)
{
var thisMd = nodeModel.MethodDetails;
thisMd.ActingInstanceType = newMd.ActingInstanceType; // 更新方法需要的类型
var thisPds = thisMd.ParameterDetailss;
var newPds = newMd.ParameterDetailss;
// 当前存在可变参数,且新的方法也存在可变参数,需要把可变参数的数目与值传递过去
if (thisMd.HasParamsArg && newMd.HasParamsArg)
{
int paramsLength = thisPds.Length - thisMd.ParamsArgIndex - 1; // 确定扩容长度
newMd.ParameterDetailss = ArrayHelper.Expansion(newPds, paramsLength);// 为新方法的入参参数描述进行扩容
newPds = newMd.ParameterDetailss;
int index = newMd.ParamsArgIndex; // 记录
var templatePd = newPds[newMd.ParamsArgIndex]; // 新的入参模板
for (int i = thisMd.ParamsArgIndex; i < thisPds.Length; i++)
{
ParameterDetails thisPd = thisPds[i];
var newPd = templatePd.CloneOfModel(nodeModel); // 复制参数描述
newPd.Index = i + 1; // 更新索引
newPd.IsParams = true;
newPd.DataValue = thisPd.DataValue; // 保留参数值
newPd.ArgDataSourceNodeGuid = thisPd.ArgDataSourceNodeGuid; // 保留参数来源信息
newPd.ArgDataSourceType = thisPd.ArgDataSourceType; // 保留参数来源信息
newPd.IsParams = thisPd.IsParams; // 保留显式参数设置
newPds[index++] = newPd;
}
}
var thidPdLength = thisMd.HasParamsArg ? thisMd.ParamsArgIndex : thisPds.Length;
// 遍历当前的参数描述(不包含可变参数),找到匹配项,复制必要的数据进行保留
for (int i = 0; i < thisPds.Length; i++)
{
ParameterDetails thisPd = thisPds[i];
var newPd = newPds.FirstOrDefault(t_newPd => !t_newPd.IsParams // 不为可变参数
&& t_newPd.Name.Equals(thisPd.Name, StringComparison.OrdinalIgnoreCase) // 存在相同名称
&& t_newPd.DataType.Name.Equals(thisPd.DataType.Name) // 存在相同入参类型名称(以类型作为区分)
);
if (newPd != null) // 如果匹配上了
{
newPd.DataValue = thisPd.DataValue; // 保留参数值
newPd.ArgDataSourceNodeGuid = thisPd.ArgDataSourceNodeGuid; // 保留参数来源信息
newPd.ArgDataSourceType = thisPd.ArgDataSourceType; // 保留参数来源信息
newPd.IsParams = thisPd.IsParams; // 保留显式参数设置
}
}
thisMd.ReturnType = newMd.ReturnType;
nodeModel.MethodDetails = newMd;
}
}
#endif
}

View File

@@ -0,0 +1,108 @@
using Serein.Library;
using Serein.Library.Api;
using Serein.Library.Utils;
using Serein.Library.Utils.SereinExpression;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
namespace Serein.Library
{
/// <summary>
/// 基础功能
/// </summary>
[DynamicFlow(Name ="[基础功能]")]
public class SereinBaseFunction
{
//[NodeAction(NodeType.Action,"条件节点")]
//private bool SereinConditionNode(IDynamicContext context,
// object targetObject,
// string exp = "ISPASS")
//{
// var isPass = SereinConditionParser.To(targetObject, exp);
// context.NextOrientation = isPass ? ConnectionInvokeType.IsSucceed : ConnectionInvokeType.IsFail;
// return isPass;
//}
//[NodeAction(NodeType.Action, "表达式节点")]
//private object SereinExpNode(IDynamicContext context,
// object targetObject,
// string exp)
//{
// exp = "@" + exp;
// var newData = SerinExpressionEvaluator.Evaluate(exp, targetObject, out bool isChange);
// object result;
// if (isChange || exp.StartsWith("@GET",System.StringComparison.OrdinalIgnoreCase))
// {
// result = newData;
// }
// else
// {
// result = targetObject;
// }
// context.NextOrientation = ConnectionInvokeType.IsSucceed;
// return result;
//}
[NodeAction(NodeType.Action, "键值对组装")]
private Dictionary<string, object> SereinKvDataCollectionNode(/*NodeModelBase nodeModel, */
string argName,
params object[] value)
{
//var paramsArgIndex = nodeModel.MethodDetails.ParamsArgIndex;
//var pds = nodeModel.MethodDetails.ParameterDetailss;
//var length = pds.Length - paramsArgIndex;
//for(int i = paramsArgIndex; i < pds.Length; i++)
//{
// var pd = pds[i];
//}
var names = argName.Split(';');
var count = Math.Min(value.Length, names.Length);
var dict = new Dictionary<string, object>();
for (int i = 0; i < count; i++)
{
dict[names[i]] = value[i];
}
return dict;
}
[NodeAction(NodeType.Action, "数组组装")]
private object[] SereinListDataCollectionNode(params object[] value)
{
return value;
}
[NodeAction(NodeType.Action, "输出")]
private object[] SereinConsoleNode(params object[] value)
{
foreach (var item in value)
{
Console.WriteLine(item);
}
return value;
}
/* if (!DynamicObjectHelper.TryResolve(dict, className, out var result))
{
Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
}
else
{
DynamicObjectHelper.PrintObjectProperties(result);
}
//if (!ObjDynamicCreateHelper.TryResolve(externalData, "RootType", out var result))
//{
// Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
//}
//ObjDynamicCreateHelper.PrintObjectProperties(result!);
return result;*/
}
}

View File

@@ -19,7 +19,7 @@ namespace Serein.Library.Utils
/// <param name="length">扩容长度</param>
/// <returns>新的数组</returns>
/// <exception cref="Exception"> length 传入负值</exception>
public static T[] ArrayExpansion<T>(T[] original, int length)
public static T[] Expansion<T>(T[] original, int length)
{
if(length == 0)
{
@@ -58,7 +58,10 @@ namespace Serein.Library.Utils
public static T[] AddToArray<T>(T[] original, T newObject)
{
// 创建一个新数组比原数组大1
T[] newArray = ArrayHelper.ArrayExpansion(original, 1);
T[] newArray = ArrayHelper.Expansion(original, 1);
original.CopyTo(newArray, 0);
// 将新对象放在最后一位
newArray[newArray.Length - 1] = newObject;
return newArray;

View File

@@ -0,0 +1,303 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Library.Utils
{
public class DynamicObjectHelper
{
// 类型缓存,键为类型的唯一名称(可以根据实际需求调整生成方式)
static Dictionary<string, Type> typeCache = new Dictionary<string, Type>();
public static object Resolve(IDictionary<string, object> properties, string typeName)
{
var obj = CreateObjectWithProperties(properties, typeName);
//SetPropertyValues(obj, properties);
return obj;
}
public static bool TryResolve(IDictionary<string, object> properties, string typeName, out object result)
{
result = CreateObjectWithProperties(properties, typeName);
bool success = SetPropertyValuesWithValidation(result, properties);
return success;
// 打印赋值结果
}
// 递归方法:打印对象属性及类型
public static void PrintObjectProperties(object obj, string indent = "")
{
var objType = obj.GetType();
foreach (var prop in objType.GetProperties())
{
var value = prop.GetValue(obj);
Console.WriteLine($"{indent}{prop.Name} (Type: {prop.PropertyType.Name}): {value}");
if (value != null)
{
if (prop.PropertyType.IsArray) // 处理数组类型
{
var array = (Array)value;
Console.WriteLine($"{indent}{prop.Name} is an array with {array.Length} elements:");
for (int i = 0; i < array.Length; i++)
{
var element = array.GetValue(i);
if (element != null && element.GetType().IsClass && !(element is string))
{
Console.WriteLine($"{indent}\tArray[{i}] (Type: {element.GetType().Name}) contains a nested object:");
PrintObjectProperties(element, indent + "\t\t");
}
else
{
Console.WriteLine($"{indent}\tArray[{i}] (Type: {element?.GetType().Name}): {element}");
}
}
}
else if (value.GetType().IsClass && !(value is string)) // 处理嵌套对象
{
Console.WriteLine($"{indent}{prop.Name} contains a nested object:");
PrintObjectProperties(value, indent + "\t");
}
}
}
}
// 方法 1: 创建动态类型及其对象实例
public static object CreateObjectWithProperties(IDictionary<string, object> properties, string typeName)
{
// 如果类型已经缓存,直接返回缓存的类型
if (typeCache.ContainsKey(typeName))
{
return Activator.CreateInstance(typeCache[typeName]);
}
// 定义动态程序集和模块
var assemblyName = new AssemblyName("DynamicAssembly");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
// 定义动态类型
var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
// 为每个属性名和值添加相应的属性到动态类型中
foreach (var kvp in properties)
{
string propName = kvp.Key;
object propValue = kvp.Value;
Type propType;
if (propValue is IList<Dictionary<string, object>>) // 处理数组类型
{
var nestedPropValue = (propValue as IList<Dictionary<string, object>>)[0];
var nestedType = CreateObjectWithProperties(nestedPropValue, $"{propName}Element");
propType = nestedType.GetType().MakeArrayType(); // 创建数组类型
}
else if (propValue is Dictionary<string, object> nestedProperties)
{
// 如果值是嵌套的字典,递归创建嵌套类型
propType = CreateObjectWithProperties(nestedProperties, $"{typeName}_{propName}").GetType();
}
else
{
// 如果是普通类型,使用值的类型
propType = propValue?.GetType() ?? typeof(object);
}
// 定义私有字段和公共属性
var fieldBuilder = typeBuilder.DefineField("_" + propName, propType, FieldAttributes.Private);
var propertyBuilder = typeBuilder.DefineProperty(propName, PropertyAttributes.HasDefault, propType, null);
// 定义 getter 方法
var getMethodBuilder = typeBuilder.DefineMethod(
"get_" + propName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
propType,
Type.EmptyTypes);
var getIL = getMethodBuilder.GetILGenerator();
getIL.Emit(OpCodes.Ldarg_0);
getIL.Emit(OpCodes.Ldfld, fieldBuilder);
getIL.Emit(OpCodes.Ret);
// 定义 setter 方法
var setMethodBuilder = typeBuilder.DefineMethod(
"set_" + propName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
null,
new Type[] { propType });
var setIL = setMethodBuilder.GetILGenerator();
setIL.Emit(OpCodes.Ldarg_0);
setIL.Emit(OpCodes.Ldarg_1);
setIL.Emit(OpCodes.Stfld, fieldBuilder);
setIL.Emit(OpCodes.Ret);
// 将 getter 和 setter 方法添加到属性
propertyBuilder.SetGetMethod(getMethodBuilder);
propertyBuilder.SetSetMethod(setMethodBuilder);
}
// 创建类型并缓存
var dynamicType = typeBuilder.CreateType();
typeCache[typeName] = dynamicType;
// 创建对象实例
return Activator.CreateInstance(dynamicType);
}
// 方法 2: 递归设置对象的属性值
public static void SetPropertyValues(object obj, Dictionary<string, object> properties)
{
var objType = obj.GetType();
foreach (var kvp in properties)
{
var propInfo = objType.GetProperty(kvp.Key);
object value = kvp.Value;
// 如果值是嵌套的字典类型,递归处理嵌套对象
if (value is Dictionary<string, object> nestedProperties)
{
// 创建嵌套对象
var nestedObj = Activator.CreateInstance(propInfo.PropertyType);
// 递归设置嵌套对象的值
SetPropertyValues(nestedObj, nestedProperties);
// 将嵌套对象赋值给属性
propInfo.SetValue(obj, nestedObj);
}
else
{
// 直接赋值给属性
propInfo.SetValue(obj, value);
}
}
}
// 方法 2: 递归设置对象的属性值(带验证)
public static bool SetPropertyValuesWithValidation(object obj, IDictionary<string, object> properties)
{
var objType = obj.GetType();
bool allSuccessful = true; // 标记是否所有属性赋值成功
foreach (var kvp in properties)
{
var propName = kvp.Key;
var propValue = kvp.Value;
var propInfo = objType.GetProperty(propName);
if (propInfo == null)
{
// 属性不存在,打印警告并标记失败
Console.WriteLine($"Warning: 属性 '{propName}' 不存在于类型 '{objType.Name}' 中,跳过赋值。");
allSuccessful = false;
continue;
}
// 检查属性类型是否与要赋的值兼容
var targetType = propInfo.PropertyType;
if (!IsCompatibleType(targetType, propValue))
{
// 如果类型不兼容,打印错误并标记失败
Console.WriteLine($"Error: 无法将类型 '{propValue?.GetType().Name}' 赋值给属性 '{propName}' (Type: {targetType.Name}),跳过赋值。");
allSuccessful = false;
continue;
}
try
{
// 如果值是一个嵌套对象,递归赋值
if (propValue is Dictionary<string, object> nestedProperties)
{
var nestedObj = Activator.CreateInstance(propInfo.PropertyType);
if (nestedObj != null && SetPropertyValuesWithValidation(nestedObj, nestedProperties))
{
propInfo.SetValue(obj, nestedObj);
}
else
{
allSuccessful = false; // 嵌套赋值失败
}
}
else if (propValue is IList<Dictionary<string, object>> list) // 处理列表
{
// 获取目标类型的数组元素类型
var elementType = propInfo.PropertyType.GetElementType();
if (elementType != null)
{
var array = Array.CreateInstance(elementType, list.Count);
for (int i = 0; i < list.Count; i++)
{
var item = Activator.CreateInstance(elementType);
if (item != null && SetPropertyValuesWithValidation(item, list[i]))
{
array.SetValue(item, i);
}
else
{
allSuccessful = false; // 赋值失败
}
}
propInfo.SetValue(obj, array);
}
}
else
{
// 直接赋值
propInfo.SetValue(obj, propValue);
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: 为属性 '{propName}' 赋值时发生异常:{ex.Message}");
allSuccessful = false;
}
}
return allSuccessful;
}
// 检查类型兼容性的方法(支持嵌套类型)
static bool IsCompatibleType(Type targetType, object value)
{
if (value == null)
{
// 如果值为null且目标类型是引用类型或者可空类型则兼容
return !targetType.IsValueType || Nullable.GetUnderlyingType(targetType) != null;
}
// 检查值的类型是否与目标类型相同,或是否可以转换为目标类型
if (targetType.IsAssignableFrom(value.GetType()))
{
return true;
}
// 处理数组类型
if (targetType.IsArray)
{
// 检查数组的元素类型与值的类型兼容
var elementType = targetType.GetElementType();
return value is IList<Dictionary<string, object>>; // 假设值是一个列表,具体处理逻辑在赋值时
}
// 处理嵌套类型的情况
if (value is Dictionary<string, object> && targetType.IsClass && !targetType.IsPrimitive)
{
// 如果目标类型是一个复杂对象,并且值是一个字典,可能是嵌套对象
return true; // 假设可以递归处理嵌套对象
}
return false;
}
}
}

View File

@@ -22,7 +22,7 @@ namespace Serein.Library.Utils.SereinExpression
public static T Evaluate(string expression, T inputValue)
{
// 替换占位符@为输入值
expression = expression.Replace("@", inputValue.ToString());
try
@@ -51,7 +51,7 @@ namespace Serein.Library.Utils.SereinExpression
/// <exception cref="NotSupportedException"></exception>
public static object Evaluate(string expression, object targetObJ, out bool isChange)
{
if(expression is null || targetObJ is null)
if (expression is null || targetObJ is null)
{
throw new Exception("表达式条件expression is null、 targetObJ is null");
}
@@ -88,13 +88,13 @@ namespace Serein.Library.Utils.SereinExpression
throw new NotSupportedException($"Operation {operation} is not supported.");
}
return result;
}
private static readonly char[] separator = new char[] { '(', ')' };
private static readonly char[] separator = new char[] { '(', ')' };
private static readonly char[] separatorArray = new char[] { ',' };
/// <summary>
@@ -128,6 +128,7 @@ namespace Serein.Library.Utils.SereinExpression
return method.Invoke(target, parameterValues);
}
/// <summary>
/// 获取值
/// </summary>
@@ -156,56 +157,53 @@ namespace Serein.Library.Utils.SereinExpression
}
var targetType = target?.GetType(); // 目标对象的类型
if(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
#region
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
var typetmp = target.GetType().FullName;
// 目标是键值对
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
var method = targetType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance);
if(method != null)
if (method != null)
{
var result = method.Invoke(target, new object[] { indexStr });
if(result != null)
var result = method.Invoke(target, new object[] { indexStr });
if (result != null)
{
return result;
target = result;
}
}
//var dict = target as Dictionary<string, string>;
////var dict = (Dictionary<dynamic, dynamic>)target;
//var temp = dict[indexStr];
////if (target is Dictionary<object, object> dict)
////{
//// var temp = dict[indexStr];
////}
//var TMP2= target.GetType().GetEnumValues();
}
}
#endregion
else
{
#region
// 获取数组或集合对象
var arrayProperty = target?.GetType().GetProperty(arrayName);
if (arrayProperty is null)
// 如果arrayName为空说明target可能是数组而不需要再获取属性了
if (!string.IsNullOrEmpty(arrayName))
{
var arrayField = target?.GetType().GetField(arrayName);
if (arrayField is null)
var arrayProperty = target?.GetType().GetProperty(arrayName);
if (arrayProperty is null)
{
throw new ArgumentException($"Member {arrayName} not found on target.");
var arrayField = target?.GetType().GetField(arrayName);
if (arrayField is null)
{
throw new ArgumentException($"Member {arrayName} not found on target.");
}
else
{
target = arrayField.GetValue(target);
}
}
else
{
target = arrayField.GetValue(target);
target = arrayProperty.GetValue(target);
}
}
else
{
target = arrayProperty.GetValue(target);
}
// 提取数组索引
var indexStr = member.Substring(arrayIndexStart + 1, arrayIndexEnd - arrayIndexStart - 1);
if (!int.TryParse(indexStr, out int index))
@@ -236,7 +234,6 @@ namespace Serein.Library.Utils.SereinExpression
#endregion
}
}
else
{
@@ -288,7 +285,7 @@ namespace Serein.Library.Utils.SereinExpression
// 检查是否包含数组索引
var arrayIndexStart = member.IndexOf('[');
if (arrayIndexStart != -1)
if (arrayIndexStart != -1)
{
// 解析数组名和索引
var arrayName = member.Substring(0, arrayIndexStart);
@@ -394,6 +391,7 @@ namespace Serein.Library.Utils.SereinExpression
return target;
}
/// <summary>
/// 计算数学简单表达式
/// </summary>
@@ -408,7 +406,7 @@ namespace Serein.Library.Utils.SereinExpression
private static T ComputedNumber<T>(object value, string expression) where T : struct, IComparable<T>
{
T result = value.ToConvert<T>();
return SerinArithmeticExpressionEvaluator<T>.Evaluate(expression, result);
return SerinArithmeticExpressionEvaluator<T>.Evaluate(expression, result);
}
}
}