vendredi 23 octobre 2015

LINQ Select on a dynamic type which has a property name that contains period

I have a list with instances of a dynamic type created using reflection. The dynamic type has properties with names that contain a period like HELLO.WORLD. These properties are of type string.

My goal is to select those properties with LINQ using Select

If i try the following

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

I get the error that the collection does not have HELLO property. Any idea how to select this property? Basically I need a list of string as a result.

Creation of dynamic type

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

The following is a screenshot from the debugger http://ift.tt/1Mewi5g





Aucun commentaire:

Enregistrer un commentaire