LINQ选择属性名中包含句号的动态类型

本文关键字:动态 类型 包含句 选择 属性 LINQ | 更新日期: 2023-09-27 18:19:02

我有一个使用反射创建的动态类型实例列表。动态类型的属性的名称包含像HELLO.WORLD这样的句点。这些性质为string型。

我的目标是使用Select

在LINQ中选择这些属性

如果我尝试下面的

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

LINQ选择属性名中包含句号的动态类型

你可以像访问字典一样访问动态:

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);
    }