Beispiel #1
0
 public MemberPair(MemberInfo source, MemberAccessPath target)
 {
     this.SourceMemberAccess = new MemberAccessPath {
         source
     };
     this.TargetMemberAccess = target;
 }
        internal static LambdaExpression GetSetterLambdaExpressionWithNullChecks(this MemberAccessPath memberAccessPath)
        {
            var instanceType = memberAccessPath.First().ReflectedType;
            var valueType    = memberAccessPath.Last().GetMemberType();
            var value        = Expression.Parameter(valueType, "value");

            var entryInstance = Expression.Parameter(instanceType, "instance");
            var labelTarget   = Expression.Label(typeof(void), "label");

            Expression accessPath     = entryInstance;
            var        memberAccesses = new List <Expression>();

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo methodInfo)
                {
                    if (methodInfo.IsGetterMethod())
                    {
                        accessPath = Expression.Call(accessPath, methodInfo);
                    }
                    else
                    {
                        accessPath = Expression.Call(accessPath, methodInfo, value);
                    }
                }
                else
                {
                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }

                memberAccesses.Add(accessPath);
            }

            if (!(accessPath is MethodCallExpression))
            {
                accessPath = Expression.Assign(accessPath, value);
            }

            var nullConstant = Expression.Constant(null);
            var returnVoid   = Expression.Return(labelTarget, typeof(void));

            var nullChecks = memberAccesses.Take(memberAccesses.Count - 1).Select(memberAccess =>
            {
                var equalsNull = Expression.Equal(memberAccess, nullConstant);
                return((Expression)Expression.IfThen(equalsNull, returnVoid));
            }).ToList();

            var exp = Expression.Block
                      (
                nullChecks.Any() ? Expression.Block(nullChecks.ToArray())
                    : (Expression)Expression.Empty(),

                accessPath,
                Expression.Label(labelTarget)
                      );

            var delegateType = typeof(Action <,>).MakeGenericType(instanceType, valueType);

            return(LambdaExpression.Lambda(delegateType, exp, entryInstance, value));
        }
Beispiel #3
0
        public MemberPair(MemberInfo source, MemberAccessPath target)
        {
            this.SourceMemberAccess = new MemberAccessPath();
            this.SourceMemberAccess.Add(source);

            this.TargetMemberAccess = target;
        }
Beispiel #4
0
 public MemberPair(MemberAccessPath source, MemberInfo target)
 {
     this.SourceMemberAccess = source;
     this.TargetMemberAccess = new MemberAccessPath {
         target
     };
 }
Beispiel #5
0
 public MappingSource(MemberAccessPath memberGetter)
     : base(memberGetter)
 {
     this.ValueGetter = this.MemberAccessPath.Count == 1 ?
                        this.MemberAccessPath.GetGetterExp() :
                        this.MemberAccessPath.GetGetterExpWithNullChecks();
 }
Beispiel #6
0
        public MemberPair(MemberAccessPath source, MemberInfo target)
        {
            this.SourceMemberAccess = source;

            this.TargetMemberAccess = new MemberAccessPath();
            this.TargetMemberAccess.Add(target);
        }
Beispiel #7
0
 public MemberPair(MemberInfo source, MemberAccessPath target)
 {
     this.SourceMemberPath = new MemberAccessPath(source.DeclaringType)
     {
         source
     };
     this.TargetMemberPath = target;
 }
Beispiel #8
0
 public MemberPair(MemberAccessPath source, MemberInfo target)
 {
     this.SourceMemberPath = source;
     this.TargetMemberPath = new MemberAccessPath(target.DeclaringType)
     {
         target
     };
 }
Beispiel #9
0
        internal MappingMemberBase(MemberAccessPath memberAccessPath)
        {
            this.MemberAccessPath = memberAccessPath;
            this.MemberInfo       = memberAccessPath.Last();
            this.MemberType       = this.MemberInfo.GetMemberType();

            _toString = new Lazy <string>(() =>
            {
                string typeName = this.MemberType.GetPrettifiedName();
                return($"{typeName} {this.MemberInfo.Name}");
            });
        }
Beispiel #10
0
        internal static LambdaExpression GetSetterExp(this MemberAccessPath memberAccessPath)
        {
            var        instanceType   = memberAccessPath.EntryInstance;
            var        accessInstance = Expression.Parameter(instanceType, "instance");
            Expression accessPath     = accessInstance;

            if (memberAccessPath.Count == 0)
            {
                var valueType2 = memberAccessPath.ReturnType;
                var value2     = Expression.Parameter(valueType2, "value");

                if (instanceType != memberAccessPath.ReturnType)
                {
                    accessPath = Expression.Convert(accessInstance, memberAccessPath.ReturnType);
                }

                var delegateType2 = typeof(Action <,>).MakeGenericType(instanceType, instanceType);
                return(LambdaExpression.Lambda(delegateType2, accessPath, accessInstance, value2));
            }


            var valueType   = memberAccessPath.Last().GetMemberType();
            var value       = Expression.Parameter(valueType, "value");
            var entryMember = memberAccessPath.First();

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo methodInfo)
                {
                    if (methodInfo.IsGetterMethod())
                    {
                        accessPath = Expression.Call(accessPath, methodInfo);
                    }
                    else
                    {
                        accessPath = Expression.Call(accessPath, (MethodInfo)memberAccess, value);
                    }
                }
                else
                {
                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }
            }

            if (!(accessPath is MethodCallExpression))
            {
                accessPath = Expression.Assign(accessPath, value);
            }

            var delegateType = typeof(Action <,>).MakeGenericType(instanceType, valueType);

            return(LambdaExpression.Lambda(delegateType, accessPath, accessInstance, value));
        }
        internal static LambdaExpression GetGetterLambdaExpressionWithNullChecks(this MemberAccessPath memberAccessPath)
        {
            var instanceType = memberAccessPath.First().ReflectedType;
            var returnType   = memberAccessPath.Last().GetMemberType();

            var entryInstance = Expression.Parameter(instanceType, "instance");
            var labelTarget   = Expression.Label(returnType, "label");

            Expression accessPath     = entryInstance;
            var        memberAccesses = new List <Expression>();

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo)
                {
                    accessPath = Expression.Call(accessPath, (MethodInfo)memberAccess);
                }
                else
                {
                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }

                memberAccesses.Add(accessPath);
            }

            var nullConstant = Expression.Constant(null);
            var returnNull   = Expression.Return(labelTarget, Expression.Default(returnType));

            var nullChecks = memberAccesses.Take(memberAccesses.Count - 1).Select(memberAccess =>
            {
                var equalsNull = Expression.Equal(memberAccess, nullConstant);
                return((Expression)Expression.IfThen(equalsNull, returnNull));
            }).ToList();

            var exp = Expression.Block
                      (
                nullChecks.Any() ? Expression.Block(nullChecks.ToArray())
                    : (Expression)Expression.Empty(),

                Expression.Label(labelTarget, memberAccesses.Last())
                      );

            var delegateType = typeof(Func <,>).MakeGenericType(instanceType, returnType);

            return(LambdaExpression.Lambda(delegateType, exp, entryInstance));
        }
Beispiel #12
0
        internal static LambdaExpression GetGetterExp(this MemberAccessPath memberAccessPath)
        {
            var        instanceType   = memberAccessPath.EntryInstance;
            var        accessInstance = Expression.Parameter(instanceType, "instance");
            Expression accessPath     = accessInstance;

            if (memberAccessPath.Count == 0)
            {
                if (instanceType != memberAccessPath.ReturnType)
                {
                    accessPath = Expression.Convert(accessInstance, memberAccessPath.ReturnType);
                }

                var delegateType2 = typeof(Func <,>).MakeGenericType(instanceType, instanceType);
                return(LambdaExpression.Lambda(delegateType2, accessPath, accessInstance));
            }

            var entryMember = memberAccessPath.First();
            var returnType  = memberAccessPath.Last().GetMemberType();

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo mi)
                {
                    accessPath = Expression.Call(accessPath, mi);
                }
                else
                {
                    if (memberAccess.DeclaringType != accessPath.Type)
                    {
                        accessPath = Expression.Convert(accessPath, memberAccess.DeclaringType);
                    }

                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }
            }

            var delegateType = typeof(Func <,>).MakeGenericType(instanceType, returnType);

            return(LambdaExpression.Lambda(delegateType, accessPath, accessInstance));
        }
        internal static LambdaExpression GetSetterLambdaExpression(this MemberAccessPath memberAccessPath)
        {
            var instanceType = memberAccessPath.First().ReflectedType;
            var valueType    = memberAccessPath.Last().GetMemberType();

            var value          = Expression.Parameter(valueType, "value");
            var accessInstance = Expression.Parameter(instanceType, "instance");

            Expression accessPath = accessInstance;

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo)
                {
                    var methodInfo = (MethodInfo)memberAccess;

                    if (methodInfo.IsGetterMethod())
                    {
                        accessPath = Expression.Call(accessPath, methodInfo);
                    }
                    else
                    {
                        accessPath = Expression.Call(accessPath, (MethodInfo)memberAccess, value);
                    }
                }
                else
                {
                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }
            }

            if (!(accessPath is MethodCallExpression))
            {
                accessPath = Expression.Assign(accessPath, value);
            }

            var delegateType = typeof(Action <,>).MakeGenericType(instanceType, valueType);

            return(LambdaExpression.Lambda(delegateType, accessPath, accessInstance, value));
        }
        internal static LambdaExpression GetGetterLambdaExpression(this MemberAccessPath memberAccessPath)
        {
            var instanceType = memberAccessPath.First().ReflectedType;
            var returnType   = memberAccessPath.Last().GetMemberType();

            var        accessInstance = Expression.Parameter(instanceType, "instance");
            Expression accessPath     = accessInstance;

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo)
                {
                    accessPath = Expression.Call(accessPath, (MethodInfo)memberAccess);
                }
                else
                {
                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }
            }

            var delegateType = typeof(Func <,>).MakeGenericType(instanceType, returnType);

            return(LambdaExpression.Lambda(delegateType, accessPath, accessInstance));
        }
        internal MappingTarget(MemberAccessPath memberSetter, MemberAccessPath memberGetter = null)
            : base(memberSetter)
        {
            this.ValueSetter = memberSetter.Count > 1 ?
                               memberSetter.GetSetterLambdaExpressionWithNullInstancesInstantiation() :
                               memberSetter.GetSetterLambdaExpression();

            try
            {
                //build the getter from the getter member path if provided;
                //try to figure out the getter from the setter member path otherwise
                //(this will work if the member being accessed is a field or property
                //but won't necessarily work for methods)
                this.ValueGetter = memberGetter == null
                    ? memberSetter.GetGetterLambdaExpression()
                    : memberGetter.GetGetterLambdaExpression();
            }
            catch (Exception)
            {
                //Must be provided from where to read the member.
                //We don't always have the real need to 'read' the member being set.
                //This could still be not a problem.
            }
        }
Beispiel #16
0
 internal MappingSource(MemberAccessPath memberGetter)
     : base(memberGetter)
 {
     this.ValueGetter = memberGetter.GetGetterLambdaExpression();
 }
Beispiel #17
0
 public MemberPair(MemberAccessPath source, MemberAccessPath target)
 {
     this.SourceMemberAccess = source;
     this.TargetMemberAccess = target;
 }
Beispiel #18
0
        public static MemberAccessPath GetMemberAccessPath(this Expression lambdaExpression)
        {
            if (!(lambdaExpression is LambdaExpression lambda))
            {
                throw new InvalidCastException("Invalid lambda expression");
            }

            var        stack = new Stack <Expression>();
            Expression exp   = lambda.Body;

            //we are always only interested in the left part of an assignment expression.
            if (exp.NodeType == ExpressionType.Assign)
            {
                exp = ((BinaryExpression)exp).Left;
            }

            //if the expression is a constant, we just return the type of the constant
            else if (exp.NodeType == ExpressionType.Constant)
            {
                var type = ((ConstantExpression)exp).Type;
                return(new MemberAccessPath(lambda.Type, type));
            }

            if (exp is GotoExpression expression)
            {
                stack.Push(expression.Value);
            }
            else
            {
                //break the expression down member by member
                while (!(exp is ParameterExpression))
                {
                    stack.Push(exp);

                    if (exp.NodeType == ExpressionType.Convert)
                    {
                        exp = ((UnaryExpression)exp).Operand as Expression;
                    }

                    else if (exp.NodeType == ExpressionType.MemberAccess)
                    {
                        exp = ((MemberExpression)exp).Expression;
                    }

                    else if (exp.NodeType == ExpressionType.Call)
                    {
                        exp = ((MethodCallExpression)exp).Object;
                    }
                }

                //instance parameter
                stack.Push(exp);
            }

            //If the instance on which we call is a derived class and the property
            //we select is defined in the base class, we will notice that
            //the PropertyInfo is retrieved through the base class; hence
            //DeclaredType and ReflectedType are equal and we basically
            //lose information about the ReflectedType (which should be the derived class)...
            //..to fix that we do another search.
            //We search the member we are accessing by name in the actual type we meant to use for the invocation
            //Since we support deep member accessing, things get a little more complex here
            //but we basically just follow each member access starting from the passed lambda parameter.

            //Follow member accesses starting from the lambda input parameter.
            var lambdaMember = (stack.Pop() as ParameterExpression);
            var member       = lambda.Parameters.First(
                p => p.Name == lambdaMember.Name).Type as MemberInfo;

            var memberAcessPath = new MemberAccessPath(lambdaMember.Type);

            if (stack.Count == 0)  //noticed we already popped once!
            {
                //return entry instance
                memberAcessPath.Add(member);
                memberAcessPath.ReturnType = member.GetMemberType();
            }
            else
            {
                var bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

                Type type = member.GetMemberType();
                foreach (var item in stack)
                {
                    var    expItem    = item;
                    string memberName = null;

                    if (expItem is MemberExpression memberExp)
                    {
                        memberName = memberExp.Member.Name;

                        member = type.GetMember(memberName, bindingFlags)[0];
                        type   = member.GetMemberType();
                        memberAcessPath.Add(member);
                    }
                    else if (expItem is MethodCallExpression methodCallExp)
                    {
                        memberName = methodCallExp.Method.Name;
                        member     = type.GetMember(memberName, bindingFlags)[0];
                        type       = member.GetMemberType();
                        memberAcessPath.Add(member);
                    }
                    else if (expItem is UnaryExpression unaryExp)
                    {
                        expItem = unaryExp.Operand;
                        type    = unaryExp.Type;
                    }
                }

                memberAcessPath.ReturnType = type;
            }

            return(memberAcessPath);
        }
Beispiel #19
0
        internal static LambdaExpression GetSetterExpInstantiateNullInstances(this MemberAccessPath memberAccessPath)
        {
            var instanceType = memberAccessPath.First().ReflectedType;
            var valueType    = memberAccessPath.Last().GetMemberType();
            var value        = Expression.Parameter(valueType, "value");

            var entryInstance = Expression.Parameter(instanceType, "instance");

            Expression accessPath     = entryInstance;
            var        memberAccesses = new List <Expression>();

            foreach (var memberAccess in memberAccessPath)
            {
                if (memberAccess is MethodInfo methodInfo)
                {
                    if (methodInfo.IsGetterMethod())
                    {
                        accessPath = Expression.Call(accessPath, methodInfo);
                    }
                    else
                    {
                        accessPath = Expression.Call(accessPath, methodInfo, value);
                    }
                }
                else
                {
                    accessPath = Expression.MakeMemberAccess(accessPath, memberAccess);
                }

                memberAccesses.Add(accessPath);
            }

            if (!(accessPath is MethodCallExpression))
            {
                accessPath = Expression.Assign(accessPath, value);
            }

            var nullConstant = Expression.Constant(null);
            var nullChecks   = memberAccesses.Take(memberAccesses.Count - 1).Select((memberAccess, i) =>
            {
                if (memberAccessPath[i] is MethodInfo methodInfo)
                {
                    //nested method calls like GetCustomer().SetName() include non-writable member (GetCustomer).
                    //Assigning a new instance in that case is more difficult.
                    //In that case 'by convention' we should look for:
                    // - A property named Customer
                    // - A method named SetCustomer(argument type = getter return type)
                    //      (also take into account Set, Set_, set, set_) as for convention.

                    var bindingAttributes = BindingFlags.Instance | BindingFlags.Public
                                            | BindingFlags.FlattenHierarchy | BindingFlags.NonPublic;

                    string setterMethodName = null;
                    if (methodInfo.Name.StartsWith("Get"))
                    {
                        setterMethodName = methodInfo.Name.Replace("Get", "Set");
                    }
                    else if (methodInfo.Name.StartsWith("get"))
                    {
                        setterMethodName = methodInfo.Name.Replace("get", "set");
                    }
                    else if (methodInfo.Name.StartsWith("Get_"))
                    {
                        setterMethodName = methodInfo.Name.Replace("Get_", "Set_");
                    }
                    else if (methodInfo.Name.StartsWith("get_"))
                    {
                        setterMethodName = methodInfo.Name.Replace("get_", "set_");
                    }

                    var setterMethod = methodInfo.ReflectedType.GetMethod(setterMethodName, bindingAttributes);

                    Expression setterAccessPath = entryInstance;
                    for (int j = 0; j < i; j++)
                    {
                        if (memberAccessPath[j] is MethodInfo mi)
                        {
                            if (mi.IsGetterMethod())
                            {
                                setterAccessPath = Expression.Call(accessPath, mi);
                            }
                            else
                            {
                                setterAccessPath = Expression.Call(accessPath, mi, value);
                            }
                        }
                        else
                        {
                            setterAccessPath = Expression.MakeMemberAccess(setterAccessPath, memberAccessPath[j]);
                        }
                    }

                    setterAccessPath = Expression.Call(setterAccessPath, setterMethod, Expression.New(memberAccess.Type));
                    var equalsNull   = Expression.Equal(memberAccess, nullConstant);
                    return((Expression)Expression.IfThen(equalsNull, setterAccessPath));
                }
                else
                {
                    var createInstance = Expression.Assign(memberAccess, Expression.New(memberAccess.Type));
                    var equalsNull     = Expression.Equal(memberAccess, nullConstant);
                    return((Expression)Expression.IfThen(equalsNull, createInstance));
                }
            }).Where(nc => nc != null).ToList();

            var exp = Expression.Block
                      (
                nullChecks.Any() ? Expression.Block(nullChecks.ToArray())
                    : (Expression)Expression.Empty(),

                accessPath
                      );

            var delegateType = typeof(Action <,>).MakeGenericType(instanceType, valueType);

            return(LambdaExpression.Lambda(delegateType, exp, entryInstance, value));
        }
Beispiel #20
0
 internal MappingMemberBase(MemberAccessPath memberAccessPath)
 {
     this.MemberAccessPath = memberAccessPath;
     this.MemberInfo       = memberAccessPath.Last();
     this.MemberType       = this.MemberInfo.GetMemberType();
 }
 public MappingTarget GetMappingTarget(MemberInfo targetMember,
                                       MemberAccessPath targetMemberPath)
 {
     return(_targetProperties.GetOrAdd(targetMember,
                                       () => new MappingTarget(targetMemberPath)));
 }
 public MappingSource GetMappingSource(MemberInfo sourceMember,
                                       MemberAccessPath sourceMemberPath)
 {
     return(_sourceProperties.GetOrAdd(sourceMember,
                                       () => new MappingSource(sourceMemberPath)));
 }
Beispiel #23
0
 public MappingPoint(MemberAccessPath memberAccessPath)
 {
     this.MemberAccessPath = memberAccessPath;
     this.MemberInfo       = memberAccessPath.LastOrDefault() ?? memberAccessPath.EntryInstance;
     this.MemberType       = this.MemberInfo.GetMemberType();
 }