diff --git a/Source/TinyMapper/Bindings/BindingConfig.cs b/Source/TinyMapper/Bindings/BindingConfig.cs index d7b101c..1db2fef 100644 --- a/Source/TinyMapper/Bindings/BindingConfig.cs +++ b/Source/TinyMapper/Bindings/BindingConfig.cs @@ -8,7 +8,7 @@ namespace Nelibur.ObjectMapper.Bindings internal class BindingConfig { private readonly Dictionary _oneToOneBindFields = new Dictionary(); - private readonly Dictionary _bindFieldsPath = new Dictionary(); + private readonly Dictionary> _bindFieldsPath = new Dictionary>(); private readonly Dictionary _bindTypes = new Dictionary(); private readonly Dictionary> _customTypeConverters = new Dictionary>(); private readonly HashSet _ignoreFields = new HashSet(); @@ -28,7 +28,14 @@ internal void BindFields(List sourcePath, List targetPath) } else { - _bindFieldsPath[bindingFieldPath.SourceHead] = bindingFieldPath; + if (_bindFieldsPath.ContainsKey(bindingFieldPath.SourceHead)) + { + _bindFieldsPath[bindingFieldPath.SourceHead].Add(bindingFieldPath); + } + else + { + _bindFieldsPath[bindingFieldPath.SourceHead] = new List { bindingFieldPath }; + } } } @@ -44,11 +51,11 @@ internal Option GetBindField(string sourceName) return new Option(result, exsist); } - internal Option GetBindFieldPath(string fieldName) + internal Option> GetBindFieldPath(string fieldName) { - BindingFieldPath result; + List result; bool exsist = _bindFieldsPath.TryGetValue(fieldName, out result); - return new Option(result, exsist); + return new Option>(result, exsist); } internal Option GetBindType(string targetName) diff --git a/Source/TinyMapper/Mappers/Classes/Members/MappingMemberBuilder.cs b/Source/TinyMapper/Mappers/Classes/Members/MappingMemberBuilder.cs index b8b94f4..20f2b77 100644 --- a/Source/TinyMapper/Mappers/Classes/Members/MappingMemberBuilder.cs +++ b/Source/TinyMapper/Mappers/Classes/Members/MappingMemberBuilder.cs @@ -178,6 +178,7 @@ private List ParseMappingTypes(TypePair typePair) MemberInfo targetMember = targetMembers.FirstOrDefault(x => _config.NameMatching(targetName, x.Name)); if (targetMember.IsNull()) { + result.AddRange(GetBindMappingMemberPath(typePair, bindingConfig, sourceMember)); continue; } Option concreteBindingType = bindingConfig.Map(x => x.GetBindType(targetName)); @@ -191,13 +192,25 @@ private List ParseMappingTypes(TypePair typePair) result.Add(new MappingMemberPath(sourceMember, targetMember)); } - var bindFieldPath = bindingConfig.Map(x => x.GetBindFieldPath(sourceMember.Name)); + result.AddRange(GetBindMappingMemberPath(typePair, bindingConfig, sourceMember)); + } + return result; + } - if (bindFieldPath.HasValue) + private List GetBindMappingMemberPath(TypePair typePair, Option bindingConfig, MemberInfo sourceMember) + { + var result = new List(); + + var bindFieldPath = bindingConfig.Map(x => x.GetBindFieldPath(sourceMember.Name)); + + if (bindFieldPath.HasValue) + { + foreach (var item in bindFieldPath.Value) { - var sourceMemperPath = GetSourceMemberPath(bindFieldPath.Value.SourcePath, typePair.Source); - var targetMemperPath = GetSourceMemberPath(bindFieldPath.Value.TargetPath, typePair.Target); + var sourceMemperPath = GetSourceMemberPath(item.SourcePath, typePair.Source); + var targetMemperPath = GetSourceMemberPath(item.TargetPath, typePair.Target); result.Add(new MappingMemberPath(sourceMemperPath, targetMemperPath)); + } } return result; diff --git a/Source/TinyMapper/Reflection/DynamicAssemblyBuilder.cs b/Source/TinyMapper/Reflection/DynamicAssemblyBuilder.cs index 08f92d3..8a727f5 100644 --- a/Source/TinyMapper/Reflection/DynamicAssemblyBuilder.cs +++ b/Source/TinyMapper/Reflection/DynamicAssemblyBuilder.cs @@ -8,8 +8,8 @@ internal class DynamicAssemblyBuilder { internal const string AssemblyName = "DynamicTinyMapper"; #if !COREFX - private const string AssemblyNameFileName = AssemblyName + ".dll"; - private static AssemblyBuilder _assemblyBuilder; +// private const string AssemblyNameFileName = AssemblyName + ".dll"; +// private static AssemblyBuilder _assemblyBuilder; #endif private static readonly DynamicAssembly _dynamicAssembly = new DynamicAssembly(); @@ -32,11 +32,11 @@ public DynamicAssembly() _moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name); #else -// AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); - _assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); + AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run); +// _assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); -// _moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name); - _moduleBuilder = _assemblyBuilder.DefineDynamicModule(assemblyName.Name, AssemblyNameFileName, true); + _moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name); +// _moduleBuilder = _assemblyBuilder.DefineDynamicModule(assemblyName.Name, AssemblyNameFileName, true); #endif } @@ -49,7 +49,7 @@ public TypeBuilder DefineType(string typeName, Type parentType) public void Save() { #if !COREFX - _assemblyBuilder.Save(AssemblyNameFileName); +// _assemblyBuilder.Save(AssemblyNameFileName); #endif } } diff --git a/Source/UnitTests/ForTests.cs b/Source/UnitTests/ForTests.cs index 70110d8..c2fcbbd 100644 --- a/Source/UnitTests/ForTests.cs +++ b/Source/UnitTests/ForTests.cs @@ -8,8 +8,8 @@ namespace UnitTests { public sealed class ForTests { -// [Fact(Skip = "ForTests")] - [Fact] + [Fact(Skip = "ForTests")] +// [Fact] public void Test() { // TinyMapper.Bind(); diff --git a/Source/UnitTests/Mappings/MappingWithComplexConfigTests.cs b/Source/UnitTests/Mappings/MappingWithComplexConfigTests.cs new file mode 100644 index 0000000..94b6ab0 --- /dev/null +++ b/Source/UnitTests/Mappings/MappingWithComplexConfigTests.cs @@ -0,0 +1,64 @@ +using Nelibur.ObjectMapper; +using Xunit; + +namespace UnitTests.Mappings +{ + public class MappingWithComplexConfigTests + { + [Fact] + public void Map_ComplexBind_Success() + { + TinyMapper.Bind( + config => + { + config.Bind(source => source.Address.Street, target => target.Street); + config.Bind(source => source.Address.Phone, target => target.Phone); + } + ); + + var dto = new PersonDto + { + Address = new AddressDto + { + Street = "Street", + Phone = "123123" + }, + Code = "Code", + Identity = 1, + Name = "Alex" + }; + + var person = TinyMapper.Map(dto); + + Assert.Equal(dto.Identity, person.Identity); + Assert.Equal(dto.Code, person.Code); + Assert.Equal(dto.Name, person.Name); + Assert.Equal(dto.Address.Street, person.Street); + Assert.Equal(dto.Address.Phone, person.Phone); + } + + + public class Person + { + public int Identity { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public string Street { get; set; } + public string Phone { get; set; } + } + + public class PersonDto + { + public int Identity { get; set; } + public string Code { get; set; } + public string Name { get; set; } + public AddressDto Address { get; set; } + } + + public class AddressDto + { + public string Street { get; set; } + public string Phone { get; set; } + } + } +}