private static Expression BuildRelationUpdateBlock( EntityFieldInfo fromKey, PropertyInfo fromProperty, EntityInfo toEntity, PropertyInfo toProperty, Expression varFromEntity, Expression varDict) { var actions = new List <Expression>(); /** * var posts = dict[blog.BlogId]; * blog.Posts.AddRange(posts); */ var toEnumType = typeof(IEnumerable <>).MakeGenericType(toEntity.Type); var fkExpr = Expression.Property(varFromEntity, fromKey.ClrProperty); // var posts = dicts[blog.BlogId]; var varTs = Expression.Variable(toEnumType, "rts"); var keyType = varDict.Type.GenericTypeArguments.First(); var castExpr = Expression.Convert(fkExpr, keyType); var dictItemExpr = Expression.Property(varDict, "Item", castExpr); var varTsAssignExpr = Expression.Assign(varTs, dictItemExpr); actions.Add(varTsAssignExpr); if (fromProperty != null) { // blog.Posts.AddRange(posts); var fmExpr = Expression.Property(varFromEntity, fromProperty); var constructor = fmExpr.Type.GetConstructor(new[] { varTs.Type }); var cExpr = Expression.New(constructor, varTs); var arcExpr = Expression.Assign(fmExpr, cExpr); actions.Add(arcExpr); } /** * foreach (var post in posts) * post.Blog = blog; */ if (toProperty != null) { var varToEntity = Expression.Parameter(toEntity.Type, "t"); var tfmExpr = Expression.Property(varToEntity, toProperty); var tfmAssignExpr = Expression.Assign(tfmExpr, varFromEntity); var tkLoop = MakeForEach(varTs, varToEntity, tfmAssignExpr); actions.Add(tkLoop); } var updateBlockExpr = Expression.Block(new[] { varTs }, actions.ToArray()); // ContainsKey(TKey key) var ccExpr = Expression.Call(varDict, "ContainsKey", null, castExpr); var ifExpr = Expression.IfThen(ccExpr, updateBlockExpr); return(ifExpr); }
private static MethodCallExpression GetToDictCall(EntityInfo toEntity, EntityFieldInfo toKey, Expression toParam) { // GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) var gParam = Expression.Parameter(toEntity.Type, "t"); var gBody = Expression.Property(gParam, toKey.ClrProperty); var gLambda = Expression.Lambda(gBody, gParam); var gCall = Expression.Call(typeof(Enumerable), nameof(Enumerable.GroupBy), new[] { gParam.Type, gBody.Type }, toParam, gLambda); // ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) var tdParam = Expression.Parameter(typeof(IGrouping <,>).MakeGenericType(toKey.ValType, toEntity.Type)); var tdBody = Expression.Property(tdParam, "Key"); var tdLambda = Expression.Lambda(tdBody, tdParam); var tdCall = Expression.Call(typeof(Enumerable), nameof(Enumerable.ToDictionary), new[] { tdParam.Type, tdBody.Type }, gCall, tdLambda); return(tdCall); }
private static LambdaExpression MakeFillerFunc( Expression memberExpr, Type fromEnumType, Type toEnumType, EntityInfo fromEntity, EntityInfo toEntity, EntityFieldInfo fromKey, EntityFieldInfo toKey, PropertyInfo fromProp, PropertyInfo toProp) { var fromParam = Expression.Parameter(typeof(List <object>), "fs"); var toParam = Expression.Parameter(typeof(List <object>), "ts"); var varFromArr = Expression.Variable(fromEnumType, "fromArr"); var varToArr = Expression.Variable(toEnumType, "toArr"); var fromCastCall = Expression.Call(typeof(Enumerable), nameof(Enumerable.Cast), new[] { fromEntity.Type }, fromParam); var toCastCall = Expression.Call(typeof(Enumerable), nameof(Enumerable.Cast), new[] { toEntity.Type }, toParam); var varFromArrAssign = Expression.Assign(varFromArr, fromCastCall); var varToArrAssign = Expression.Assign(varToArr, toCastCall); // create dictionary for toEntities // var dicts = ps.GroupBy(p => p.BlogId).ToDictionary(bid => bid.Key); var tdCall = GetToDictCall(toEntity, toKey, varToArr); var varDict = Expression.Variable(tdCall.Type, "toDict"); var varDictAssignExpr = Expression.Assign(varDict, tdCall); var varFromEntity = Expression.Parameter(fromEntity.Type, "f"); var ifExpr = BuildRelationUpdateBlock(fromKey, fromProp, toEntity, toProp, varFromEntity, varDict); var forEachExpr = MakeForEach(varFromArr, varFromEntity, ifExpr); var codeBlock = Expression.Block( new[] { varFromArr, varToArr, varDict }, varFromArrAssign, varToArrAssign, varDictAssignExpr, forEachExpr); return(toEnumType.IsAssignableFrom(memberExpr.Type) ? Expression.Lambda(codeBlock, fromParam, toParam) : Expression.Lambda(codeBlock, toParam, fromParam)); }