示例#1
0
        public static IQueryable<Package> Search(this IQueryable<Package> source, string searchTerm)
        {
            // Split the search terms by spaces
            var terms = (searchTerm ?? String.Empty).Split();

            // Build a list of expressions for each term
            var expressions = new List<LambdaExpression>();
            foreach (var criteria in searchCriteria)
            {
                foreach (var term in terms)
                {
                    expressions.Add(criteria(term));
                }
            }

            // Build a giant or statement using the bodies of the lambdas
            var body = expressions.Select(p => p.Body)
                                  .Aggregate(Expression.OrElse);

            // Now build the final predicate
            var parameterExpr = Expression.Parameter(typeof(Package));

            // Fix up the body to use our parameter expression
            body = new ParameterExpressionReplacer(parameterExpr).Visit(body);

            // Build the final predicate
            var predicate = Expression.Lambda<Func<Package, bool>>(body, parameterExpr);

            // Apply it to the query
            return source.Where(predicate);
        }
示例#2
0
        protected Expression CreateAdaptToExpression(Expression source, Expression destination, CompileArgument arg)
        {
            if (destination == null)
            {
                return(CreateAdaptExpression(source, arg.DestinationType, arg));
            }

            if (source.Type == destination.Type && arg.Settings.ShallowCopyForSameType == true)
            {
                return(source);
            }

            //adapt(source, dest);
            var lambda = arg.Context.Config.CreateInlineMapExpression(source.Type, destination.Type, arg.MapType, arg.Context);
            var exp    = lambda.Apply(source, destination);

            //transform(adapt(source, dest));
            if (arg.Settings.DestinationTransforms.Transforms.ContainsKey(exp.Type))
            {
                var transform = arg.Settings.DestinationTransforms.Transforms[exp.Type];
                var replacer  = new ParameterExpressionReplacer(transform.Parameters, exp);
                var newExp    = replacer.Visit(transform.Body);
                exp = replacer.ReplaceCount >= 2 ? Expression.Invoke(transform, exp) : newExp;
            }
            return(exp.To(destination.Type));
        }
    public static Expression <Func <TTarget, bool> > ConvertTo <TSource, TTarget>(this Expression <Func <TSource, bool> > source, Expression <Func <TTarget, TSource> > sourceSelector)
    {
        var body = new ParameterExpressionReplacer {
            source = source.Parameters[0], target = sourceSelector.Body
        }.Visit(source.Body);
        var lambda = Expression.Lambda <Func <TTarget, bool> >(body, sourceSelector.Parameters);

        return(lambda);
    }
        private Expression <Func <StoredEntry, bool> > TranslatePredicate(Expression <Func <IEntryState <TId, TData>, bool> > predicate)
        {
            Assert(predicate != null);

            var parameter = Expression.Parameter(typeof(StoredEntry));
            var body      = ParameterExpressionReplacer.ReplaceParameter(predicate.Body, predicate.Parameters.First(), parameter);

            return(Expression.Lambda <Func <StoredEntry, bool> >(body, parameter));
        }
示例#5
0
    public static Expression <Func <TOuter, TResult> > Bind <TOuter, TInner, TResult>(this Expression <Func <TOuter, TInner> > source, Expression <Func <TInner, TResult> > resultSelector)
    {
        var body = new ParameterExpressionReplacer {
            source = resultSelector.Parameters[0], target = source.Body
        }.Visit(resultSelector.Body);
        var lambda = Expression.Lambda <Func <TOuter, TResult> >(body, source.Parameters);

        return(lambda);
    }
示例#6
0
        public static IQueryable <Package> Search(this IQueryable <Package> source, string searchTerm)
        {
            if (String.IsNullOrWhiteSpace(searchTerm))
            {
                return(source);
            }

            // Split the search terms by spaces
            var terms = (searchTerm ?? String.Empty).Split();

            // Build a list of expressions for each term
            var expressions = new List <LambdaExpression>();

            foreach (var term in terms)
            {
                var localSearchTerm = term.to_lower();

                if (localSearchTerm.StartsWith("id:"))
                {
                    expressions.Add(idCriteria(localSearchTerm.Replace("id:", string.Empty)));
                }
                if (localSearchTerm.StartsWith("author:"))
                {
                    expressions.Add(authorCriteria(localSearchTerm.Replace("author:", string.Empty)));
                }
                else if (localSearchTerm.StartsWith("tag:"))
                {
                    expressions.Add(tagCriteria(localSearchTerm.Replace("tag:", string.Empty)));
                }
                else
                {
                    foreach (var criteria in searchCriteria)
                    {
                        expressions.Add(criteria(localSearchTerm));
                    }
                }
            }

            //todo this becomes an AND
            // Build a giant or statement using the bodies of the lambdas
            var body = expressions.Select(p => p.Body)
                       .Aggregate(Expression.OrElse);

            // Now build the final predicate
            var parameterExpr = Expression.Parameter(typeof(Package));

            // Fix up the body to use our parameter expression
            body = new ParameterExpressionReplacer(parameterExpr).Visit(body);

            // Build the final predicate
            var predicate = Expression.Lambda <Func <Package, bool> >(body, parameterExpr);

            // Apply it to the query
            return(source.Where(predicate));
        }
示例#7
0
        private Expression <TDelegate> ConvertExpression <TDelegate>(LambdaExpression expression)
            where TDelegate : Delegate
        {
            var parameter = expression.Parameters.First();
            var body      = expression.Body;

            var newParameter = Expression.Parameter(typeof(TRemote));
            var newBody      = ParameterExpressionReplacer.ReplaceParameter(body, parameter, newParameter);

            return(Expression.Lambda <TDelegate>(newBody, newParameter));
        }
示例#8
0
        public static IQueryable<Package> Search(this IQueryable<Package> source, string searchTerm)
        {
            if (String.IsNullOrWhiteSpace(searchTerm))
            {
                return source;
            }

            // Split the search terms by spaces
            var terms = (searchTerm ?? String.Empty).Split();

            // Build a list of expressions for each term
            var expressions = new List<LambdaExpression>();
            foreach (var term in terms)
            {
                var localSearchTerm = term.to_lower();

                if (localSearchTerm.StartsWith("id:"))
                {
                    expressions.Add(idCriteria(localSearchTerm.Replace("id:", string.Empty)));
                }
                if (localSearchTerm.StartsWith("author:"))
                {
                    expressions.Add(authorCriteria(localSearchTerm.Replace("author:", string.Empty)));
                }
                else if (localSearchTerm.StartsWith("tag:"))
                {
                    expressions.Add(tagCriteria(localSearchTerm.Replace("tag:", string.Empty)));
                } else
                {
                    foreach (var criteria in searchCriteria)
                    {
                        expressions.Add(criteria(localSearchTerm));
                    }
                }
            }

            //todo this becomes an AND
            // Build a giant or statement using the bodies of the lambdas
            var body = expressions.Select(p => p.Body)
                                  .Aggregate(Expression.OrElse);

            // Now build the final predicate
            var parameterExpr = Expression.Parameter(typeof(Package));

            // Fix up the body to use our parameter expression
            body = new ParameterExpressionReplacer(parameterExpr).Visit(body);

            // Build the final predicate
            var predicate = Expression.Lambda<Func<Package, bool>>(body, parameterExpr);

            // Apply it to the query
            return source.Where(predicate);
        }
示例#9
0
        public static Expression <Func <TSource, bool> > And <TSource>(this Expression <Func <TSource, bool> > a, Expression <Func <TSource, bool> > b)
        {
            Type typeFromHandle = typeof(TSource);
            ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "root");
            Expression          left  = ParameterExpressionReplacer.Replace(a.Body, parameterExpression);
            Expression          right = ParameterExpressionReplacer.Replace(b.Body, parameterExpression);
            BinaryExpression    body  = Expression.And(left, right);

            return(Expression.Lambda <Func <TSource, bool> >(body, new ParameterExpression[]
            {
                parameterExpression
            }));
        }
示例#10
0
        private static Expression <Func <TEntry, bool> > BuildPredicate <TEntry>(TEntry comparand,
                                                                                 Expression <Func <TEntry, TEntry, bool> > equalityComparer)
        {
            Assert(comparand != null);
            Assert(equalityComparer != null);

            var idSelector        = DataPropertyHelper.BuildPredicate(comparand);
            var comparandConstant = Expression.Constant(comparand, typeof(TEntry));
            var parameter         = equalityComparer.Parameters.First();
            var equality          = ParameterExpressionReplacer.ReplaceParameter(equalityComparer.Body, equalityComparer.Parameters.Last(), comparandConstant);
            var idEquality        = ParameterExpressionReplacer.ReplaceParameter(idSelector.Body, idSelector.Parameters.First(), parameter);
            var body = Expression.AndAlso(idEquality, equality);

            return(Expression.Lambda <Func <TEntry, bool> >(body, parameter));
        }
示例#11
0
        protected Expression CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg)
        {
            if (source.Type == destinationType && (arg.Settings.ShallowCopyForSameType == true || arg.MapType == MapType.Projection))
                return source.To(destinationType);

            var lambda = arg.Context.Config.CreateInlineMapExpression(source.Type, destinationType, arg.MapType, arg.Context);
            var exp = lambda.Apply(source);

            if (arg.Settings.DestinationTransforms.Transforms.ContainsKey(exp.Type))
            {
                var transform = arg.Settings.DestinationTransforms.Transforms[exp.Type];
                var replacer = new ParameterExpressionReplacer(transform.Parameters, exp);
                var newExp = replacer.Visit(transform.Body);
                exp = replacer.ReplaceCount >= 2 ? Expression.Invoke(transform, exp) : newExp;
            }
            return exp.To(destinationType);
        }
        public static Expression <Func <TDataRepresentation, bool> > TranslatePredicate <TId, TData, TDataRepresentation>(Expression <Func <TData, bool> > predicate)
            where TData : class
            where TDataRepresentation : class, IDataRepresentation <TId, TData>
        {
            // The resulting predicate checks
            // 1) If the entry's payload matches the specified predicate.
            // 2) If the entry's data is not null (The entry is not deleted)

            var parameter    = Expression.Parameter(typeof(TDataRepresentation));
            var dataAccessor = DataHelper <TId, TData> .Accessor;
            var nullConstant = DataHelper <TId, TData> .Null;

            var data             = ParameterExpressionReplacer.ReplaceParameter(dataAccessor.Body, dataAccessor.Parameters.First(), parameter);
            var isNull           = Expression.ReferenceEqual(data, nullConstant);
            var isNotNull        = Expression.Not(isNull);
            var matchesPredicate = ParameterExpressionReplacer.ReplaceParameter(predicate.Body, predicate.Parameters.First(), data);
            var body             = Expression.AndAlso(isNotNull, matchesPredicate);

            return(Expression.Lambda <Func <TDataRepresentation, bool> >(body, parameter));
        }
示例#13
0
        public static LambdaExpression And(this LambdaExpression a, LambdaExpression b)
        {
            if (a == null)
            {
                return(b);
            }
            if (b == null)
            {
                return(a);
            }

            Type rootType    = a.Parameters[0].Type;
            var  memberParam = Expression.Parameter(rootType, "root");
            var  aNewBody    = ParameterExpressionReplacer.Replace(a.Body, memberParam);
            var  bNewBody    = ParameterExpressionReplacer.Replace(b.Body, memberParam);
            var  newBody     = Expression.And(aNewBody, bNewBody);
            var  lambda      = Expression.Lambda(a.Type, newBody, memberParam);

            return(lambda);
        }
示例#14
0
        private static Expression <Func <TEntry, TEntry, bool> > BuildEqualityComparer <TEntry, TVersion>(Expression <Func <TEntry, TVersion> > versionSelector)
            where TEntry : class
            where TVersion : IEquatable <TVersion>
        {
            Assert(versionSelector != null);

            var param1 = Expression.Parameter(typeof(TEntry), "left");
            var param2 = Expression.Parameter(typeof(TEntry), "right");

            var version1 = ParameterExpressionReplacer.ReplaceParameter(versionSelector.Body, versionSelector.Parameters.First(), param1);
            var version2 = ParameterExpressionReplacer.ReplaceParameter(versionSelector.Body, versionSelector.Parameters.First(), param2);

            var equalityMethod = typeof(IEquatable <TVersion>).GetMethod(nameof(Equals));

            Assert(equalityMethod != null);

            var call = Expression.Call(version1, equalityMethod, version2);

            Expression equality;

            if (typeof(TVersion).IsValueType)
            {
                equality = call;
            }
            else // (left == null && right == null) || (left != null && right != null && left.Equals(right));
            {
                var isNull1    = Expression.Equal(version1, Expression.Constant(null, typeof(TVersion)));
                var isNull2    = Expression.Equal(version2, Expression.Constant(null, typeof(TVersion)));
                var isNotNull1 = Expression.Not(isNull1);
                var isNotNull2 = Expression.Not(isNull2);

                var bothNull    = Expression.AndAlso(isNull1, isNull2);
                var bothNotNUll = Expression.AndAlso(isNotNull1, isNotNull2);

                equality = Expression.OrElse(bothNull, Expression.AndAlso(bothNotNUll, call));
            }

            return(Expression.Lambda <Func <TEntry, TEntry, bool> >(equality, param1, param2));
        }
示例#15
0
        public static IQueryable <Package> Search(this IQueryable <Package> source, string searchTerm)
        {
            if (String.IsNullOrWhiteSpace(searchTerm))
            {
                return(source);
            }

            // Split the search terms by spaces
            var terms = searchTerm.Split();

            // Build a list of expressions for each term
            var expressions = new List <LambdaExpression>();

            foreach (var criteria in SearchCriteria)
            {
                foreach (var term in terms)
                {
                    expressions.Add(criteria(term));
                }
            }

            // Build a giant or statement using the bodies of the lambdas
            var body = expressions.Select(p => p.Body)
                       .Aggregate(Expression.OrElse);

            // Now build the final predicate
            var parameterExpr = Expression.Parameter(typeof(Package));

            // Fix up the body to use our parameter expression
            body = new ParameterExpressionReplacer(parameterExpr).Visit(body);

            // Build the final predicate
            var predicate = Expression.Lambda <Func <Package, bool> >(body, parameterExpr);

            // Apply it to the query
            return(source.Where(predicate));
        }
示例#16
0
        protected Expression CreateBlockExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            if (arg.MapType == MapType.Projection)
                throw new InvalidOperationException(
                    $"Mapping is invalid for projection: TSource: {arg.SourceType} TDestination: {arg.DestinationType}");

            var result = Expression.Variable(arg.DestinationType);
            Expression assign = Expression.Assign(result, destination ?? CreateInstantiationExpression(source, arg));

            var set = CreateBlockExpression(source, result, arg);

            if (arg.Settings.AfterMappingFactories.Count > 0)
            {
                //var result = adapt(source);
                //action(source, result);

                var actions = new List<Expression> { set };

                foreach (var afterMappingFactory in arg.Settings.AfterMappingFactories)
                {
                    var afterMapping = afterMappingFactory(arg);
                    var args = afterMapping.Parameters;
                    Expression invoke;
                    if (args[0].Type.IsReferenceAssignableFrom(source.Type) && args[1].Type.IsReferenceAssignableFrom(result.Type))
                    {
                        var replacer = new ParameterExpressionReplacer(args, source, result);
                        invoke = replacer.Visit(afterMapping.Body);
                    }
                    else
                    {
                        invoke = Expression.Invoke(afterMapping, source.To(args[0].Type), result.To(args[1].Type));
                    }
                    actions.Add(invoke);
                }

                set = Expression.Block(actions);
            }

            if (arg.Settings.PreserveReference == true &&
                !arg.SourceType.GetTypeInfo().IsValueType &&
                !arg.DestinationType.GetTypeInfo().IsValueType)
            {
                //using (var scope = new MapContextScope()) {
                //  var dict = scope.Context.Reference;
                //  object cache;
                //  if (dict.TryGetValue(source, out cache))
                //      result = (TDestination)cache;
                //  else {
                //      result = new TDestination();
                //      dict.Add(source, (object)result);
                //      result.Prop1 = adapt(source.Prop1);
                //      result.Prop2 = adapt(source.Prop2);
                //  }
                //}

                var scope = Expression.Variable(typeof(MapContextScope));
                var newScope = Expression.Assign(scope, Expression.New(typeof(MapContextScope)));

                var dict = Expression.Variable(typeof(Dictionary<object, object>));
                var refContext = Expression.Property(scope, "Context");
                var refDict = Expression.Property(refContext, "References");
                var assignDict = Expression.Assign(dict, refDict);

                var refAdd = Expression.Call(dict, "Add", null, Expression.Convert(source, typeof(object)), Expression.Convert(result, typeof(object)));
                var setResultAndCache = Expression.Block(assign, refAdd, set);

                var cached = Expression.Variable(typeof(object));
                var tryGetMethod = typeof(Dictionary<object, object>).GetMethod("TryGetValue", new[] { typeof(object), typeof(object).MakeByRefType() });
                var checkHasRef = Expression.Call(dict, tryGetMethod, source, cached);
                var setResult = Expression.IfThenElse(
                    checkHasRef,
                    ExpressionEx.Assign(result, cached),
                    setResultAndCache);
                var usingBody = Expression.Block(new[] { cached, dict }, assignDict, setResult);

                var dispose = Expression.Call(scope, "Dispose", null);
                set = Expression.Block(new[] { scope }, newScope, Expression.TryFinally(usingBody, dispose));
            }
            else
            {
                set = Expression.Block(assign, set);
            }

            //TDestination result;
            //if (source == null)
            //  result = default(TDestination);
            //else
            //  result = adapt(source);
            //return result;
            if (!arg.SourceType.GetTypeInfo().IsValueType || arg.SourceType.IsNullable())
            {
                var compareNull = Expression.Equal(source, Expression.Constant(null, source.Type));
                set = Expression.IfThenElse(
                    compareNull,
                    Expression.Assign(result, destination ?? Expression.Constant(arg.DestinationType.GetDefault(), arg.DestinationType)),
                    set);
            }

            return Expression.Block(new[] { result }, set, result);
        }
示例#17
0
        public static IQueryable <Package> Search(this IQueryable <Package> source, string searchTerm, bool lowerCaseExpression = true)
        {
            if (String.IsNullOrWhiteSpace(searchTerm))
            {
                return(source);
            }

            // Split the search terms by spaces
            var terms = (searchTerm ?? String.Empty).Split();

            var idSearch     = searchTerm.to_lower().Contains("id:");
            var authorSearch = searchTerm.to_lower().Contains("author:");
            var tagSearch    = searchTerm.to_lower().Contains("tag:");

            // Build a list of expressions for each term
            var expressions = new List <LambdaExpression>();

            foreach (var term in terms)
            {
                // doesn't matter if this is lowercased or not
                var localSearchTerm = term.to_lower().Replace("id:", string.Empty).Replace("author:", string.Empty).Replace("tag:", string.Empty);

                if (idSearch)
                {
                    expressions.Add(lowerCaseExpression ?
                                    idLowerCriteria(localSearchTerm)
                        : idCriteria(localSearchTerm)
                                    );
                }
                else if (authorSearch)
                {
                    expressions.Add(lowerCaseExpression ?
                                    authorLowerCriteria(localSearchTerm)
                        : authorCriteria(localSearchTerm)
                                    );
                }
                else if (tagSearch)
                {
                    expressions.Add(lowerCaseExpression ?
                                    tagLowerCriteria(localSearchTerm)
                        : tagCriteria(localSearchTerm)
                                    );
                }
                else
                {
                    var criteriaList = lowerCaseExpression ? searchLowerCriteria : searchCriteria;

                    foreach (var criteria in criteriaList)
                    {
                        expressions.Add(criteria(localSearchTerm));
                    }
                }
            }

            //todo this becomes an AND
            // Build a giant or statement using the bodies of the lambdas
            var body = expressions.Select(p => p.Body)
                       .Aggregate(Expression.OrElse);

            // Now build the final predicate
            var parameterExpr = Expression.Parameter(typeof(Package));

            // Fix up the body to use our parameter expression
            body = new ParameterExpressionReplacer(parameterExpr).Visit(body);

            // Build the final predicate
            var predicate = Expression.Lambda <Func <Package, bool> >(body, parameterExpr);

            // Apply it to the query
            return(source.Where(predicate));
        }
示例#18
0
        protected Expression CreateBlockExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            if (arg.MapType == MapType.Projection)
            {
                throw new InvalidOperationException("Mapping is invalid for projection");
            }

            //var result = new TDest();
            var        result = Expression.Variable(arg.DestinationType, "result");
            var        newObj = CreateInstantiationExpression(source, destination, arg);
            Expression assign = Expression.Assign(result, newObj);

            var set = CreateBlockExpression(source, result, arg);

            //result.prop = adapt(source.prop);
            //action(source, result);
            if (arg.Settings.AfterMappingFactories.Count > 0)
            {
                var actions = new List <Expression> {
                    set
                };

                foreach (var afterMappingFactory in arg.Settings.AfterMappingFactories)
                {
                    var        afterMapping = afterMappingFactory(arg);
                    var        args         = afterMapping.Parameters;
                    Expression invoke;
                    if (args[0].Type.IsReferenceAssignableFrom(source.Type) && args[1].Type.IsReferenceAssignableFrom(result.Type))
                    {
                        var replacer = new ParameterExpressionReplacer(args, source, result);
                        invoke = replacer.Visit(afterMapping.Body);
                    }
                    else
                    {
                        invoke = Expression.Invoke(afterMapping, source.To(args[0].Type), result.To(args[1].Type));
                    }
                    actions.Add(invoke);
                }

                set = Expression.Block(actions);
            }

            //using (var scope = new MapContextScope()) {
            //  var references = scope.Context.Reference;
            //  object cache;
            //  if (references.TryGetValue(source, out cache))
            //      result = (TDestination)cache;
            //  else {
            //      result = new TDestination();
            //      references[source] = (object)result;
            //      result.prop = adapt(source.prop);
            //  }
            //}
            if (arg.Settings.PreserveReference == true &&
                !arg.SourceType.GetTypeInfo().IsValueType&&
                !arg.DestinationType.GetTypeInfo().IsValueType)
            {
                var scope    = Expression.Variable(typeof(MapContextScope), "scope");
                var newScope = Expression.Assign(scope, Expression.New(typeof(MapContextScope)));

                var dictType   = typeof(Dictionary <object, object>);
                var dict       = Expression.Variable(dictType, "references");
                var refContext = Expression.Property(scope, "Context");
                var refDict    = Expression.Property(refContext, "References");
                var assignDict = Expression.Assign(dict, refDict);

                var indexer   = dictType.GetProperties().First(item => item.GetIndexParameters().Length > 0);
                var refAssign = Expression.Assign(
                    Expression.Property(dict, indexer, Expression.Convert(source, typeof(object))),
                    Expression.Convert(result, typeof(object)));
                var setResultAndCache = Expression.Block(assign, refAssign, set);

                var cache        = Expression.Variable(typeof(object), "cache");
                var tryGetMethod = typeof(Dictionary <object, object>).GetMethod("TryGetValue", new[] { typeof(object), typeof(object).MakeByRefType() });
                var checkHasRef  = Expression.Call(dict, tryGetMethod, source, cache);
                var setResult    = Expression.IfThenElse(
                    checkHasRef,
                    ExpressionEx.Assign(result, cache),
                    setResultAndCache);
                var usingBody = Expression.Block(new[] { cache, dict }, assignDict, setResult);

                var dispose = Expression.Call(scope, "Dispose", null);
                set = Expression.Block(new[] { scope }, newScope, Expression.TryFinally(usingBody, dispose));
            }
            else
            {
                set = Expression.Block(assign, set);
            }

            //TDestination result;
            //if (source == null)
            //  result = default(TDestination);
            //else {
            //  result = new TDestination();
            //  result.prop = adapt(source.prop);
            //}
            //return result;
            if (!arg.SourceType.GetTypeInfo().IsValueType || arg.SourceType.IsNullable())
            {
                var compareNull = Expression.Equal(source, Expression.Constant(null, source.Type));
                set = Expression.IfThenElse(
                    compareNull,
                    Expression.Assign(result, destination ?? Expression.Constant(arg.DestinationType.GetDefault(), arg.DestinationType)),
                    set);
            }

            //var drvdSource = source as TDerivedSource
            //if (drvdSource != null)
            //  result = adapt<TSource, TDest>(drvdSource);
            //else {
            //  result = new TDestination();
            //  result.prop = adapt(source.prop);
            //}
            //return result;
            foreach (var tuple in arg.Settings.Includes)
            {
                //same type, no redirect to prevent endless loop
                if (tuple.Source == arg.SourceType)
                {
                    continue;
                }

                //type is not compatible, no redirect
                if (!arg.SourceType.IsReferenceAssignableFrom(tuple.Source))
                {
                    continue;
                }

                var blocks = new List <Expression>();
                var vars   = new List <ParameterExpression>();

                var drvdSource = Expression.Variable(tuple.Source);
                vars.Add(drvdSource);

                var drvdSourceAssign = Expression.Assign(
                    drvdSource,
                    Expression.TypeAs(source, tuple.Source));
                blocks.Add(drvdSourceAssign);
                var cond = Expression.NotEqual(drvdSource, Expression.Constant(null, tuple.Source));

                ParameterExpression drvdDest = null;
                if (destination != null)
                {
                    drvdDest = Expression.Variable(tuple.Destination);
                    vars.Add(drvdDest);

                    var drvdDestAssign = Expression.Assign(
                        drvdDest,
                        Expression.TypeAs(destination, tuple.Destination));
                    blocks.Add(drvdDestAssign);
                    cond = Expression.AndAlso(
                        cond,
                        Expression.NotEqual(drvdDest, Expression.Constant(null, tuple.Destination)));
                }

                var adaptExpr = drvdDest == null
                    ? CreateAdaptExpression(drvdSource, tuple.Destination, arg)
                    : CreateAdaptToExpression(drvdSource, drvdDest, arg);

                var adapt  = Expression.Assign(result, adaptExpr);
                var ifExpr = Expression.Condition(cond, adapt, set, typeof(void));
                blocks.Add(ifExpr);
                set = Expression.Block(vars, blocks);
            }

            return(Expression.Block(new[] { result }, set, result));
        }
示例#19
0
 public static Expression Apply(this LambdaExpression lambda, params Expression[] exps)
 {
     var replacer = new ParameterExpressionReplacer(lambda.Parameters, exps);
     return replacer.Visit(lambda.Body);
 }
示例#20
0
        protected Expression CreateBlockExpressionBody(Expression source, Expression destination, CompileArgument arg)
        {
            if (arg.MapType == MapType.Projection)
            {
                throw new InvalidOperationException(
                          $"Mapping is invalid for projection: TSource: {arg.SourceType} TDestination: {arg.DestinationType}");
            }

            var        result = Expression.Variable(arg.DestinationType);
            Expression assign = Expression.Assign(result, destination ?? CreateInstantiationExpression(source, arg));

            var set = CreateBlockExpression(source, result, arg);

            if (arg.Settings.AfterMappingFactories.Count > 0)
            {
                //var result = adapt(source);
                //action(source, result);

                var actions = new List <Expression> {
                    set
                };

                foreach (var afterMappingFactory in arg.Settings.AfterMappingFactories)
                {
                    var        afterMapping = afterMappingFactory(arg);
                    var        args         = afterMapping.Parameters;
                    Expression invoke;
                    if (args[0].Type.IsReferenceAssignableFrom(source.Type) && args[1].Type.IsReferenceAssignableFrom(result.Type))
                    {
                        var replacer = new ParameterExpressionReplacer(args, source, result);
                        invoke = replacer.Visit(afterMapping.Body);
                    }
                    else
                    {
                        invoke = Expression.Invoke(afterMapping, source.To(args[0].Type), result.To(args[1].Type));
                    }
                    actions.Add(invoke);
                }

                set = Expression.Block(actions);
            }

            if (arg.Settings.PreserveReference == true &&
                !arg.SourceType.GetTypeInfo().IsValueType&&
                !arg.DestinationType.GetTypeInfo().IsValueType)
            {
                //using (var scope = new MapContextScope()) {
                //  var dict = scope.Context.Reference;
                //  object cache;
                //  if (dict.TryGetValue(source, out cache))
                //      result = (TDestination)cache;
                //  else {
                //      result = new TDestination();
                //      dict.Add(source, (object)result);
                //      result.Prop1 = adapt(source.Prop1);
                //      result.Prop2 = adapt(source.Prop2);
                //  }
                //}

                var scope    = Expression.Variable(typeof(MapContextScope));
                var newScope = Expression.Assign(scope, Expression.New(typeof(MapContextScope)));

                var dict       = Expression.Variable(typeof(Dictionary <object, object>));
                var refContext = Expression.Property(scope, "Context");
                var refDict    = Expression.Property(refContext, "References");
                var assignDict = Expression.Assign(dict, refDict);

                var refAdd            = Expression.Call(dict, "Add", null, Expression.Convert(source, typeof(object)), Expression.Convert(result, typeof(object)));
                var setResultAndCache = Expression.Block(assign, refAdd, set);

                var cached       = Expression.Variable(typeof(object));
                var tryGetMethod = typeof(Dictionary <object, object>).GetMethod("TryGetValue", new[] { typeof(object), typeof(object).MakeByRefType() });
                var checkHasRef  = Expression.Call(dict, tryGetMethod, source, cached);
                var setResult    = Expression.IfThenElse(
                    checkHasRef,
                    ExpressionEx.Assign(result, cached),
                    setResultAndCache);
                var usingBody = Expression.Block(new[] { cached, dict }, assignDict, setResult);

                var dispose = Expression.Call(scope, "Dispose", null);
                set = Expression.Block(new[] { scope }, newScope, Expression.TryFinally(usingBody, dispose));
            }
            else
            {
                set = Expression.Block(assign, set);
            }

            //TDestination result;
            //if (source == null)
            //  result = default(TDestination);
            //else
            //  result = adapt(source);
            //return result;
            if (!arg.SourceType.GetTypeInfo().IsValueType || arg.SourceType.IsNullable())
            {
                var compareNull = Expression.Equal(source, Expression.Constant(null, source.Type));
                set = Expression.IfThenElse(
                    compareNull,
                    Expression.Assign(result, destination ?? Expression.Constant(arg.DestinationType.GetDefault(), arg.DestinationType)),
                    set);
            }

            return(Expression.Block(new[] { result }, set, result));
        }