private void BuildJoiner <TCompatibleRequest>(CrudRequestConfig <TCompatibleRequest> config) { if (EntityKey == null || RequestItemKey == null) { return; } var joinInfo = typeof(EnumerableExtensions) .GetMethod("FullOuterJoin", BindingFlags.Static | BindingFlags.NonPublic) .MakeGenericMethod(typeof(object), typeof(TEntity), RequestItemKey.KeyType); var makeKeySelectorInfo = typeof(CrudBulkRequestEntityConfigBuilder <TRequest, TItem, TEntity>) .GetMethod("MakeKeySelector", BindingFlags.Static | BindingFlags.NonPublic); var itemsParam = Expression.Parameter(typeof(IEnumerable <object>)); var entitiesParam = Expression.Parameter(typeof(IEnumerable <TEntity>)); var makeLeftKeySelector = makeKeySelectorInfo.MakeGenericMethod(typeof(object), RequestItemKey.KeyType); var convLeftKeyParam = Expression.Parameter(typeof(object)); var convLeftKeyCall = Expression.Invoke( RequestItemKey.KeyExpression, Expression.Convert(convLeftKeyParam, typeof(TItem))); var leftKeyExpr = Expression.Call(makeLeftKeySelector, Expression.Lambda(convLeftKeyCall, convLeftKeyParam)); var makeRightKeySelector = makeKeySelectorInfo.MakeGenericMethod(typeof(TEntity), EntityKey.KeyType); var rightKeyExpr = Expression.Call(makeRightKeySelector, Expression.Constant(EntityKey.KeyExpression)); var joinExpr = Expression.Call(joinInfo, itemsParam, entitiesParam, leftKeyExpr, rightKeyExpr); var lambdaExpr = Expression.Lambda <Func <IEnumerable <object>, IEnumerable <TEntity>, IEnumerable <Tuple <object, TEntity> > > >( joinExpr, itemsParam, entitiesParam); config.SetEntityJoiner(lambdaExpr.Compile()); }