protected override Expression VisitMemberInit(MemberInitExpression node) { if (this.TypeMappings.TryGetValue(node.Type, out Type newType)) { var typeMap = ConfigurationProvider.CheckIfMapExists(sourceType: newType, destinationType: node.Type); //The destination becomes the source because to map a source expression to a destination expression, //we need the expressions used to create the source from the destination IEnumerable <MemberBinding> bindings = node.Bindings.Select ( binding => { Expression bindingExpression = ((MemberAssignment)binding).Expression; return(DoBind ( typeMap.GetPropertyMapByDestinationProperty(binding.Member.Name), bindingExpression, this.Visit(bindingExpression) )); } ); return(Expression.MemberInit(Expression.New(newType), bindings)); } return(base.VisitMemberInit(node)); }
protected override Expression VisitMemberInit(MemberInitExpression node) { if (this.TypeMappings.TryGetValue(node.Type, out Type newType)) { var typeMap = ConfigurationProvider.CheckIfMapExists(sourceType: newType, destinationType: node.Type); //The destination becomes the source because to map a source expression to a destination expression, //we need the expressions used to create the source from the destination IEnumerable <MemberBinding> bindings = node.Bindings.Aggregate(new List <MemberBinding>(), (list, binding) => { var propertyMap = typeMap.PropertyMaps.SingleOrDefault(item => item.DestinationName == binding.Member.Name); if (propertyMap == null) { return(list); } var sourceMember = GetSourceMember(propertyMap); if (sourceMember == null) { return(list); } Expression bindingExpression = ((MemberAssignment)binding).Expression; list.Add ( DoBind ( sourceMember, bindingExpression, this.Visit(bindingExpression) ) ); return(list); }); return(Expression.MemberInit(Expression.New(newType), bindings)); } return(base.VisitMemberInit(node)); }
protected void FindDestinationFullName(Type typeSource, Type typeDestination, string sourceFullName, List <PropertyMapInfo> propertyMapInfoList) { const string period = "."; if (typeSource == typeDestination) { var sourceFullNameArray = sourceFullName.Split(new[] { period[0] }, StringSplitOptions.RemoveEmptyEntries); sourceFullNameArray.Aggregate(propertyMapInfoList, (list, next) => { if (list.Count == 0) { AddPropertyMapInfo(typeSource, next, list); } else { var last = list[list.Count - 1]; AddPropertyMapInfo(last.CustomExpression == null ? last.DestinationPropertyInfos[last.DestinationPropertyInfos.Count - 1].GetMemberType() : last.CustomExpression.ReturnType, next, list); } return(list); }); return; } if (GenericTypeDefinitionsAreEquivalent(typeSource, typeDestination)) { if (sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) < 0) { //sourceFullName is a member of the generic type definition so just add the members PropertyMapInfo AddPropertyMapInfo(typeDestination, sourceFullName, propertyMapInfoList); var sourceType = typeSource.GetFieldOrProperty(sourceFullName).GetMemberType(); var destType = typeDestination.GetFieldOrProperty(sourceFullName).GetMemberType(); TypeMappings.AddTypeMapping(ConfigurationProvider, sourceType, destType); return; } else { //propertyName is a member of the generic type definition so just add the members PropertyMapInfo var propertyName = sourceFullName.Substring(0, sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase)); AddPropertyMapInfo(typeDestination, propertyName, propertyMapInfoList); var sourceType = typeSource.GetFieldOrProperty(propertyName).GetMemberType(); var destType = typeDestination.GetFieldOrProperty(propertyName).GetMemberType(); TypeMappings.AddTypeMapping(ConfigurationProvider, sourceType, destType); var childFullName = sourceFullName.Substring(sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) + 1); FindDestinationFullName(sourceType, destType, childFullName, propertyMapInfoList); return; } } var typeMap = ConfigurationProvider.CheckIfMapExists(sourceType: typeDestination, destinationType: typeSource);//The destination becomes the source because to map a source expression to a destination expression, //we need the expressions used to create the source from the destination PathMap pathMap = typeMap.FindPathMapByDestinationPath(destinationFullPath: sourceFullName); if (pathMap != null) { propertyMapInfoList.Add(new PropertyMapInfo(pathMap.CustomMapExpression, new List <MemberInfo>())); return; } if (sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) < 0) { var propertyMap = typeMap.GetPropertyMapByDestinationProperty(sourceFullName); var sourceMemberInfo = typeSource.GetFieldOrProperty(propertyMap.DestinationMember.Name); if (propertyMap.ValueResolverConfig != null) { throw new InvalidOperationException(Resource.customResolversNotSupported); } if (propertyMap.CustomMapExpression == null && !propertyMap.SourceMembers.Any()) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.srcMemberCannotBeNullFormat, typeSource.Name, typeDestination.Name, sourceFullName)); } CompareSourceAndDestLiterals ( propertyMap.CustomMapExpression != null ? propertyMap.CustomMapExpression.ReturnType : propertyMap.SourceMember.GetMemberType(), propertyMap.CustomMapExpression != null ? propertyMap.CustomMapExpression.ToString() : propertyMap.SourceMember.Name, sourceMemberInfo.GetMemberType() ); void CompareSourceAndDestLiterals(Type mappedPropertyType, string mappedPropertyDescription, Type sourceMemberType) { //switch from IsValueType to IsLiteralType because we do not want to throw an exception for all structs if ((mappedPropertyType.IsLiteralType() || sourceMemberType.IsLiteralType()) && sourceMemberType != mappedPropertyType) { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.expressionMapValueTypeMustMatchFormat, mappedPropertyType.Name, mappedPropertyDescription, sourceMemberType.Name, propertyMap.DestinationMember.Name)); } } propertyMapInfoList.Add(new PropertyMapInfo(propertyMap.CustomMapExpression, propertyMap.SourceMembers.ToList())); } else { var propertyName = sourceFullName.Substring(0, sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase)); var propertyMap = typeMap.GetPropertyMapByDestinationProperty(propertyName); var sourceMemberInfo = typeSource.GetFieldOrProperty(propertyMap.DestinationMember.Name); if (propertyMap.CustomMapExpression == null && !propertyMap.SourceMembers.Any())//If sourceFullName has a period then the SourceMember cannot be null. The SourceMember is required to find the ProertyMap of its child object. { throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resource.srcMemberCannotBeNullFormat, typeSource.Name, typeDestination.Name, propertyName)); } propertyMapInfoList.Add(new PropertyMapInfo(propertyMap.CustomMapExpression, propertyMap.SourceMembers.ToList())); var childFullName = sourceFullName.Substring(sourceFullName.IndexOf(period, StringComparison.OrdinalIgnoreCase) + 1); FindDestinationFullName(sourceMemberInfo.GetMemberType(), propertyMap.CustomMapExpression == null ? propertyMap.SourceMember.GetMemberType() : propertyMap.CustomMapExpression.ReturnType, childFullName, propertyMapInfoList); } }