예제 #1
0
        private static MemberInitExpression GenerateNewBody(SelectedModel selectedModel, Expression source, Type newType, int level = 0)
        {
            var binding = new List <MemberAssignment>();

            foreach (var property in selectedModel.Properties)
            {
                if (TypesHelper.TypeIsComplex(property.OriginalType) && TypesHelper.TypeIsCollection(property.OriginalType))
                {
                    var newPropertyInfo        = newType.GetProperty(property.RequestedName);
                    var collectionArgumentType = newPropertyInfo.PropertyType.GetGenericArguments()[0];
                    var newSource            = Expression.Parameter(TypesHelper.GetEntityTypeFromComplex(property.OriginalType), "x" + level.ToString());
                    var newBody              = GenerateNewBody(property, newSource, collectionArgumentType, level++);
                    var selectOriginProperty = Expression.Property(source, property.Name);

                    var funcType = typeof(Func <,>).MakeGenericType(TypesHelper.GetEntityTypeFromComplex(property.OriginalType), collectionArgumentType);
                    var selectLambdaExpression = Expression.Lambda(funcType, newBody, newSource);
                    var memberAssignment       = Expression.Call(typeof(Enumerable), "Select", new Type[] { TypesHelper.GetEntityTypeFromComplex(property.OriginalType), collectionArgumentType }, selectOriginProperty, selectLambdaExpression);
                    var memberAssignment2      = Expression.Bind(newPropertyInfo, memberAssignment);
                    binding.Add(memberAssignment2);
                }
                else if (TypesHelper.TypeIsComplex(property.OriginalType))
                {
                    var newPropertyInfo  = newType.GetProperty(property.RequestedName);
                    var memberAssignment = Expression.Bind(newPropertyInfo, GenerateNewBody(property, Expression.Property(source, property.Name), newPropertyInfo.PropertyType, level++));

                    binding.Add(memberAssignment);
                }
                else
                {
                    var memberAssignment = Expression.Bind(newType.GetProperty(property.Name), Expression.Property(source, property.Name));

                    binding.Add(memberAssignment);
                }
            }

            var newExp = Expression.New(newType);
            var body   = Expression.MemberInit(newExp, binding);

            return(body);
        }
예제 #2
0
        internal static Type CreateNewType(SelectedModel selectedModel,
                                           ModuleBuilder dynamicModule = null)
        {
            if (dynamicModule == null)
            {
                dynamicModule = CreateModule();
            }

            TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("SelectWrap" + TypesHelper.GetEntityTypeFromComplex(selectedModel.OriginalType).Name, TypeAttributes.Public);

            foreach (var p in selectedModel.Properties)
            {
                Type type = TypesHelper.TypeIsComplex(p.OriginalType) ?  TypesHelper.TypeIsCollection(p.OriginalType) ? typeof(IEnumerable <>).MakeGenericType(CreateNewType(p, dynamicModule)) : CreateNewType(p, dynamicModule) : p.OriginalType;

                var field    = dynamicAnonymousType.DefineField("_" + p.Name, type, FieldAttributes.Private);
                var property = dynamicAnonymousType.DefineProperty(p.Name, PropertyAttributes.HasDefault, type, null);

                MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;

                // Define the "get" accessor method for CustomerName.
                MethodBuilder propertyGet = dynamicAnonymousType.DefineMethod("get_" + p.Name, getSetAttr, type, Type.EmptyTypes);

                ILGenerator custNameGetIL = propertyGet.GetILGenerator();

                custNameGetIL.Emit(OpCodes.Ldarg_0);
                custNameGetIL.Emit(OpCodes.Ldfld, field);
                custNameGetIL.Emit(OpCodes.Ret);

                // Define the "set" accessor method for CustomerName.
                MethodBuilder propertySet = dynamicAnonymousType.DefineMethod("set_" + p.Name, getSetAttr, null, new Type[] { type });

                ILGenerator custNameSetIL = propertySet.GetILGenerator();

                custNameSetIL.Emit(OpCodes.Ldarg_0);
                custNameSetIL.Emit(OpCodes.Ldarg_1);
                custNameSetIL.Emit(OpCodes.Stfld, field);
                custNameSetIL.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(propertyGet);
                property.SetSetMethod(propertySet);
            }
            return(dynamicAnonymousType.CreateType());
        }