LINQ选择属性名中包含句号的动态类型
本文关键字:动态 类型 包含句 选择 属性 LINQ | 更新日期: 2023-09-27 18:19:02
我有一个使用反射创建的动态类型实例列表。动态类型的属性的名称包含像HELLO.WORLD
这样的句点。这些性质为string
型。
我的目标是使用Select
如果我尝试下面的
var lstResult = ((IEnumerable<dynamic>)mydynamicdata).Select(d => d.HELLO.WORLD).AsEnumerable().ToList();
我得到的错误,收集不具有HELLO
属性。知道如何选择这个属性吗?基本上,我需要一个字符串列表作为结果。
创建动态类型
private object CreateDynamicObject(IEnumerable<string> columnsNames)
{
Type dynamicType = GetDynamicType(columnsNames);
object generetedObject = Activator.CreateInstance(dynamicType);
return generetedObject;
}
private Type CreateDynamicObjectType(IEnumerable<string> columnNames)
{
// create a dynamic assembly and module
var assemblyName = new AssemblyName { Name = "tmpAssembly" };
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder module = assemblyBuilder.DefineDynamicModule("tmpModule");
// create a new type builder
TypeBuilder typeBuilder = module.DefineType("BindableRow", TypeAttributes.Public | TypeAttributes.Class);
foreach (var header in columnNames)
{
AddProperty(typeBuilder, header, typeof(string));
}
// Generate our type
Type generetedType = typeBuilder.CreateType();
return generetedType;
}
private void AddProperty(TypeBuilder typeBuilder, string propertyName, Type type)
{
FieldBuilder field = typeBuilder.DefineField("_" + propertyName, typeof(string), FieldAttributes.Private);
// Generate a public property
PropertyBuilder property = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, type, null);
// The property set and property get methods require a special set of attributes:
const MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
// Define the "get" accessor method for current private field.
MethodBuilder currGetPropMthdBldr = typeBuilder.DefineMethod("get_" + property.Name, getSetAttr, type, Type.EmptyTypes);
// Intermediate Language stuff...
ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);
// Define the "set" accessor method for current private field.
MethodBuilder currSetPropMthdBldr = typeBuilder.DefineMethod("set_" + property.Name, getSetAttr, null, new Type[] { type });
// Again some Intermediate Language stuff...
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);
// Last, we must map the two methods created above to our PropertyBuilder to
// their corresponding behaviors, "get" and "set" respectively.
property.SetGetMethod(currGetPropMthdBldr);
property.SetSetMethod(currSetPropMthdBldr);
}
下面是调试器的屏幕截图https://i.stack.imgur.com/0seiF.png
你可以像访问字典一样访问动态:
var lstResult = ((IEnumerable<dynamic>)mydynamicdata).Select(d => d["HELLO.WORLD"]).AsEnumerable().ToList();
如果不能正常工作,下面可能会有帮助:https://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trygetindex.aspx
一个解决方案是再次使用反射来获取值
((IEnumerable<dynamic>)mydynamicdata).Select(d => GetPropValue(d,"COMO.NAME")).AsEnumerable().ToList();
和GetPropValue函数
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}