LINQ选择动态类型,其属性名称包含句点

时间:2015-10-23 14:05:22

标签: c# linq select dynamic reflection

我有一个列表,其中包含使用反射创建的动态类型的实例。动态类型具有名称包含类似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);
    }

以下是调试器的屏幕截图 http://i.imgur.com/eydF46P.png

2 个答案:

答案 0 :(得分:0)

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

var lstResult = ((IEnumerable<dynamic>)mydynamicdata).Select(d => d["HELLO.WORLD"]).AsEnumerable().ToList();

如果这不起作用,这可能会有所帮助:https://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trygetindex.aspx

答案 1 :(得分:0)

一种解决方案是再次使用反射来获取值

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

但实际上原来的问题还没有答案......