/// <summary> /// Map member /// </summary> public Expression MapModelMember(MemberExpression memberExpression, Expression accessExpression, Type modelType = null) { ClassMap classMap = this.m_mapFile.GetModelClassMap(modelType ?? memberExpression.Expression.Type); if (classMap == null) { return(accessExpression); } // Expression is the same class? Collapse if it is a key MemberExpression accessExpressionAsMember = accessExpression as MemberExpression; CollapseKey collapseKey = null; PropertyMap propertyMap = null; if (memberExpression.Member.Name == "Key" && classMap.TryGetCollapseKey(accessExpressionAsMember?.Member.Name, out collapseKey)) { return(Expression.MakeMemberAccess(accessExpressionAsMember.Expression, accessExpressionAsMember.Expression.Type.GetRuntimeProperty(collapseKey.KeyName))); } else if (classMap.TryGetModelProperty(memberExpression.Member.Name, out propertyMap)) { // We have to map through an associative table if (propertyMap.Via != null) { Expression viaExpression = Expression.MakeMemberAccess(accessExpression, accessExpression.Type.GetRuntimeProperty(propertyMap.DomainName)); var via = propertyMap.Via; while (via != null) { MemberInfo viaMember = viaExpression.Type.GetRuntimeProperty(via.DomainName); if (viaMember == null) { break; } viaExpression = Expression.MakeMemberAccess(viaExpression, viaMember); if (via.OrderBy != null && viaExpression.Type.FindInterfaces((o, _) => o == typeof(IEnumerable), null).Length > 0) { viaExpression = viaExpression.Sort(via.OrderBy, via.SortOrder); } if (via.Aggregate != AggregationFunctionType.None) { viaExpression = viaExpression.Aggregate(via.Aggregate); } via = via.Via; } return(viaExpression); } else { return(Expression.MakeMemberAccess(accessExpression, this.ExtractDomainType(accessExpression.Type).GetRuntimeProperty(propertyMap.DomainName))); } } else { // look for idenical named property Type domainType = this.MapModelType(modelType ?? memberExpression.Expression.Type); // Get domain member and map MemberInfo domainMember = accessExpression.Type.GetRuntimeProperty(memberExpression.Member.Name); if (domainMember != null) { return(Expression.MakeMemberAccess(accessExpression, domainMember)); } else { // Try on the base? if (classMap.ParentDomainProperty != null) { domainMember = domainType.GetRuntimeProperty(classMap.ParentDomainProperty.DomainName); return(MapModelMember(memberExpression, Expression.MakeMemberAccess(accessExpression, domainMember), (modelType ?? memberExpression.Expression.Type).BaseType)); } else { //Debug.WriteLine(String.Format("Cannot find property information for {0}({1}).{2}", memberExpression.Expression, memberExpression.Expression.Type.Name, memberExpression.Member.Name)); return(null); } } } }
/// <summary> /// Try to get a collapse key /// </summary> public bool TryGetCollapseKey(string propertyName, out CollapseKey retVal) { retVal = this.CollapseKey.Find(o => o.PropertyName == propertyName); return(retVal != null); }