如何在Runtime动态创建匿名类型并填充legs数组?
运行时创建含动态元素数量的匿名类型
针对你的需求,匿名类型的结构(字段名、类型)是固定的,仅legs数组的元素数量需要在运行时动态生成,这里提供两种实用方案:
方法一:LINQ+匿名类型推断(最简洁高效)
匿名类型的类型信息由编译器在编译时推断,我们可以先基于固定字段完成类型映射,再通过LINQ将运行时数据源(List<DataRow>或自定义结构体集合)转换成对应匿名类型的数组,最后组装外层匿名类型。
针对自定义结构体数据源
假设你有如下结构体定义:
public struct LegInfo { public string InstrumentType; public string Symbol; public string Quantity; public string Action; }
转换代码示例:
// 模拟运行时获取的结构体列表 List<LegInfo> legSource = new List<LegInfo> { new LegInfo { InstrumentType = "Equity Option", Symbol = "SPY 221021C00422000", Quantity = "1", Action = "Buy to Open" }, new LegInfo { InstrumentType = "Equity Option", Symbol = "SPY 221021C00420000", Quantity = "1", Action = "Sell to Open" } }; // 转换为匿名类型数组 var legs = legSource.Select(l => new { instrumenttype = l.InstrumentType, symbol = l.Symbol, quantity = l.Quantity, action = l.Action }).ToArray(); // 组装外层匿名类型 var orderFields = new { legs = legs };
针对List数据源
如果数据源是数据库查询返回的List<DataRow>,只需调整字段映射逻辑:
List<DataRow> rowSource = ...; // 从DataTable获取的行集合 var legs = rowSource.Select(row => new { instrumenttype = row["instrumenttype"].ToString(), symbol = row["symbol"].ToString(), quantity = row["quantity"].ToString(), action = row["action"].ToString() }).ToArray(); var orderFields = new { legs = legs };
方法二:反射创建匿名类型(仅复杂场景备用)
如果你的场景中匿名类型的字段无法提前确定(但你的需求里字段是固定的,此方法非必要),可以通过反射动态生成匿名类型,但代码繁琐且性能较差,示例如下:
using System.Reflection; using System.Reflection.Emit; // 工具类:动态生成匿名类型 public static class AnonymousTypeCreator { public static Type CreateAnonymousType(IDictionary<string, Type> fieldTypes) { var assemblyName = new AssemblyName("DynamicAnonymousTypes"); var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); var moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule"); // 匿名类型默认是密封类,带CompilerGenerated特性 var typeBuilder = moduleBuilder.DefineType($"<>f__AnonymousType{Guid.NewGuid():N}", TypeAttributes.Public | TypeAttributes.Sealed | TypeAttributes.Class); // 添加字段和属性 foreach (var field in fieldTypes) { var fieldBuilder = typeBuilder.DefineField($"<{field.Key}>i__Field", field.Value, FieldAttributes.Private | FieldAttributes.InitOnly); var propertyBuilder = typeBuilder.DefineProperty(field.Key, PropertyAttributes.None, field.Value, null); // 属性get方法实现 var getMethod = typeBuilder.DefineMethod($"get_{field.Key}", MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, field.Value, Type.EmptyTypes); var il = getMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, fieldBuilder); il.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getMethod); } // 生成构造函数 var ctorParams = fieldTypes.Values.ToArray(); var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, ctorParams); il = ctorBuilder.GetILGenerator(); for (int i = 0; i < ctorParams.Length; i++) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg, i + 1); il.Emit(OpCodes.Stfld, typeBuilder.GetField($"<{fieldTypes.Keys.ElementAt(i)}>i__Field")); } il.Emit(OpCodes.Ret); return typeBuilder.CreateType(); } } // 使用示例 var legFieldTypes = new Dictionary<string, Type> { { "instrumenttype", typeof(string) }, { "symbol", typeof(string) }, { "quantity", typeof(string) }, { "action", typeof(string) } }; Type legType = AnonymousTypeCreator.CreateAnonymousType(legFieldTypes); // 创建单个leg实例 object legInstance = Activator.CreateInstance(legType, "Equity Option", "SPY 221021C00422000", "1", "Buy to Open"); // 创建数组并填充 Array legsArray = Array.CreateInstance(legType, 2); legsArray.SetValue(legInstance, 0); // 填充第二个元素... // 创建外层匿名类型 var outerFieldTypes = new Dictionary<string, Type> { { "legs", legsArray.GetType() } }; Type outerType = AnonymousTypeCreator.CreateAnonymousType(outerFieldTypes); var orderFields = Activator.CreateInstance(outerType, legsArray);
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

