protected internal void AddMapping <TProperty>(ExcelPropertyMap mapping, Expression <Func <T, TProperty> > expression) { var expressionBody = expression.Body; var expressions = new Stack <MemberExpression>(); while (true) { if (!(expressionBody is MemberExpression memberExpressionBody)) { // Each mapping is of the form (parameter => member). if (expressionBody is ParameterExpression _) { break; } throw new ArgumentException($"Expression can only contain member accesses, but found {expressionBody}.", nameof(expression)); } expressions.Push(memberExpressionBody); expressionBody = memberExpressionBody.Expression; } if (expressions.Count == 1) { // Simple case: parameter => prop Mappings.Add(mapping); } else { // Go through the chain of members and make sure that they are valid. // E.g. parameter => parameter.prop.subprop.field. CreateObjectMap(mapping, expressions); } }
private void CreateObjectMapGeneric <TProperty>(ExcelPropertyMap propertyMap, MemberExpression memberExpression, Stack <MemberExpression> memberExpressions) { ExcelPropertyMap map = Properties.FirstOrDefault(m => m.Member.Equals(memberExpression.Member)); ExcelClassMap <TProperty> objectPropertyMap; if (map == null) { objectPropertyMap = new ExcelClassMap <TProperty>(); Properties.Add(new ExcelPropertyMap(memberExpression.Member, objectPropertyMap)); } else if (!(map.Map is ExcelClassMap <TProperty> existingMap)) { throw new InvalidOperationException($"Expression is already mapped differently as {map.GetType().ToString()}."); } else { objectPropertyMap = existingMap; } objectPropertyMap.CreateObjectMap(propertyMap, memberExpressions); }
/// <summary> /// Traverses through a list of member expressions, starting with the member closest to the type /// of this class map, and creates a map for each sub member access. /// This enables support for expressions such as p => p.prop.subprop.field.final. /// </summary> /// <param name="propertymap">The map for the final member access in the stack.</param> /// <param name="memberExpressions">A stack of each MemberExpression in the list of member access expressions.</param> protected internal void CreateObjectMap(ExcelPropertyMap propertymap, Stack <MemberExpression> memberExpressions) { MemberExpression memberExpression = memberExpressions.Pop(); if (memberExpressions.Count == 0) { // This is the final member. Properties.Add(propertymap); return; } Type memberType = memberExpression.Member.MemberType(); MethodInfo method = MapObjectMethod.MakeGenericMethod(memberType); try { method.Invoke(this, new object[] { propertymap, memberExpression, memberExpressions }); } catch (TargetInvocationException exception) { throw exception.InnerException; } }