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)); }
public MemberPair(MemberInfo source, MemberAccessPath target) { this.SourceMemberAccess = new MemberAccessPath(); this.SourceMemberAccess.Add(source); this.TargetMemberAccess = target; }
public MemberPair(MemberAccessPath source, MemberInfo target) { this.SourceMemberAccess = source; this.TargetMemberAccess = new MemberAccessPath { target }; }
public MappingSource(MemberAccessPath memberGetter) : base(memberGetter) { this.ValueGetter = this.MemberAccessPath.Count == 1 ? this.MemberAccessPath.GetGetterExp() : this.MemberAccessPath.GetGetterExpWithNullChecks(); }
public MemberPair(MemberAccessPath source, MemberInfo target) { this.SourceMemberAccess = source; this.TargetMemberAccess = new MemberAccessPath(); this.TargetMemberAccess.Add(target); }
public MemberPair(MemberInfo source, MemberAccessPath target) { this.SourceMemberPath = new MemberAccessPath(source.DeclaringType) { source }; this.TargetMemberPath = target; }
public MemberPair(MemberAccessPath source, MemberInfo target) { this.SourceMemberPath = source; this.TargetMemberPath = new MemberAccessPath(target.DeclaringType) { target }; }
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}"); }); }
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)); }
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. } }
internal MappingSource(MemberAccessPath memberGetter) : base(memberGetter) { this.ValueGetter = memberGetter.GetGetterLambdaExpression(); }
public MemberPair(MemberAccessPath source, MemberAccessPath target) { this.SourceMemberAccess = source; this.TargetMemberAccess = target; }
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); }
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)); }
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))); }
public MappingPoint(MemberAccessPath memberAccessPath) { this.MemberAccessPath = memberAccessPath; this.MemberInfo = memberAccessPath.LastOrDefault() ?? memberAccessPath.EntryInstance; this.MemberType = this.MemberInfo.GetMemberType(); }