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