public MappingTarget(MemberAccessPath memberSetter, MemberAccessPath memberGetter = null) : base(memberSetter) { this.ValueSetter = memberSetter.Count > 1 ? memberSetter.GetSetterExpWithNullInstancesInstantiation() : memberSetter.GetSetterExp(); 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.GetGetterExp() : memberGetter.GetGetterExp(); } 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 (we need to write it). //This could still be not a problem. } }
internal static LambdaExpression GetGetterExpWithNullChecks(this MemberAccessPath memberAccessPath) { if (memberAccessPath.Count == 0) { return(memberAccessPath.GetGetterExp()); } if (memberAccessPath.Count == 1) { return(memberAccessPath.First().GetGetterExp()); } var instanceType = memberAccessPath.EntryInstance; var entryMember = memberAccessPath.First(); 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 mi) { accessPath = Expression.Call(accessPath, mi); } else { if (memberAccess.DeclaringType != accessPath.Type) { accessPath = Expression.Convert(accessPath, memberAccess.DeclaringType); } 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)); }