public static void Examples() { Register(); var original = new HasSingle { ID = 99, Prop = new PropB { ID = 12, Value = "prop b" } }; var copyDest = new Copy();//nothing here //mapping continue down the object graph to terminal valueType nodes unless set explicitly to ignore AutoMapper.Mapper.Map(original, copyDest); //this is false, 'copyDest's Prop is a new object on the heap Console.WriteLine(string.Format("original equals copyDest: {0}", original.Prop.Equals(copyDest.Prop))); HasSingle getAnotherCopy = AutoMapper.Mapper.Map <Copy, HasSingle>(copyDest); //yet another independent copy on the heap with another stack-residing reference Console.WriteLine(string.Format("copy from copy equals original: {0}", getAnotherCopy.Equals(original))); Console.WriteLine(string.Format("copy of copy's properties equal original: {0}", getAnotherCopy.Prop.Equals(original.Prop))); PropA copiedToAnotherType = AutoMapper.Mapper.Map <PropB, PropA>(getAnotherCopy.Prop); Console.WriteLine(string.Format("copy across types with same property name/types {0}", (copiedToAnotherType != null))); //have dealt in the 'Register' the complexities of going from List<PropA> to just PropB //and, likewise, from PropB to List<PropA> so this works as expected and is, again, new //objects on the heap HasList fromTypeToGenericOfType = AutoMapper.Mapper.Map <HasSingle, HasList>(getAnotherCopy); HasSingle fromGenericOfTypeToType = AutoMapper.Mapper.Map <HasList, HasSingle>(fromTypeToGenericOfType); // in "Register" dealt with how to convert ProbValue, PropID from "HasSingle's" Prop property // and, likewise, how to take "HasSingle's" Prop property's ID, Value and copy them over to // "HasValueOfPropB's" top-level value-type properties HasValueOfPropB moveValuesUpObjGraph = AutoMapper.Mapper.Map <HasSingle, HasValueOfPropB>(fromGenericOfTypeToType); HasSingle moveValuesDownObjGraph = AutoMapper.Mapper.Map <HasValueOfPropB, HasSingle>(moveValuesUpObjGraph); PropC primaryPropC = new PropC { ID = 14, Value = "is primary", Primary = true }; PropC secondaryPropC = new PropC { ID = 11, Value = "is secondary", Primary = false }; PropB copiedFromPrimary = AutoMapper.Mapper.Map <PropC, PropB>(primaryPropC); PropB copiedFromSecondary = AutoMapper.Mapper.Map <PropC, PropB>(secondaryPropC); Console.WriteLine("in line ternary operations allowed in mappings {0}", copiedFromPrimary.ID == primaryPropC.ID && copiedFromPrimary.Value == primaryPropC.Value); Console.WriteLine("and resolves on both of the ternary operands {0}", copiedFromSecondary.ID != secondaryPropC.ID && copiedFromSecondary.Value != secondaryPropC.Value); //when a mapping already exist for two types, and some object HAS-A List of one of //those two, the mapping at the object level may operate on the list (using a LINQ expression) //which may override and ternary operations at play on the List's type var ListOfPropC = new List <PropC> { new PropC { ID = 1, Primary = false, Value = "1" }, //both the ternary operator and new PropC { ID = 2, Primary = true, Value = "2" }, //the Linq expression use this same 'Primary' property new PropC { ID = 3, Primary = false, Value = "3" }, //making them exclusive of each other new PropC { ID = 4, Primary = true, Value = "4" } }; HasListWithFlags listWithFlags = new HasListWithFlags { ID = 99, Props = ListOfPropC, Value = "with flags" }; HasList usesDuplexOfMappingRules = AutoMapper.Mapper.Map <HasListWithFlags, HasList>(listWithFlags); Console.WriteLine(string.Format("object copied with duplex of mapping rules {0}", usesDuplexOfMappingRules != null)); Console.WriteLine(string.Format("rules on list applied over rules on type therein {0}", usesDuplexOfMappingRules.Props.Count == 2)); //when the operation on the source is simply to complex to do inline, then define a seperate function //to perform this logic, declare and instantiate a function pointer to it (Func<>) and used it within //the mapping on the source. CopyToHasListWithFlags complexLogicWithinMapping = AutoMapper.Mapper.Map <HasListWithFlags, CopyToHasListWithFlags>(listWithFlags); var functionPtrWasUsed = complexLogicWithinMapping != null; Console.WriteLine(string.Format("the complex mapping returned the dest type {0}", functionPtrWasUsed)); functionPtrWasUsed = complexLogicWithinMapping.Prop != null; Console.WriteLine(string.Format("the complex mapping called the function pointer {0}", functionPtrWasUsed)); var prop = complexLogicWithinMapping.Prop; functionPtrWasUsed = prop.ID == byte.MaxValue && prop.Value == "something special" && prop.Primary; Console.WriteLine(string.Format("and operated as expected {0}", functionPtrWasUsed)); var extendedType = new ExtendsUnderlyingType { ID = 32, ValueOne = "value one", ValueTwo = "value two" }; var testMappingExtendedTypes = AutoMapper.Mapper.Map <UnderlyingType, ExtendedTypesTarget>(extendedType); Console.WriteLine(string.Format("the mapper returned something when given a concrete instance for a map on an Interface '{0}'", testMappingExtendedTypes != null)); Console.WriteLine(string.Format("The value from ID -> TheID is '{0}'", testMappingExtendedTypes.TheID)); var hasAExtendedTypeProp = new HasAExtendedUnderlyingType(); hasAExtendedTypeProp.TopId = 99; hasAExtendedTypeProp.TheHASA = extendedType; var testMappingHasAExtendedType = AutoMapper.Mapper.Map <HasAExtendedUnderlyingType, HasAMappingTarget>(hasAExtendedTypeProp); Console.WriteLine(string.Format("the call to Map did not return null '{0}'", testMappingHasAExtendedType != null)); Console.WriteLine(string.Format("the top level class ID copied fine '{0}'", hasAExtendedTypeProp.TopId == testMappingHasAExtendedType.TheTopID)); Console.WriteLine(string.Format("the child object, the point of this test, also copied '{0}'", testMappingHasAExtendedType.TheHASATarget != null)); Console.WriteLine(string.Format("the child object's ID copied as well '{0}'", testMappingHasAExtendedType.TheHASATarget.TheID == extendedType.ID)); //attempt it in reverse var testMappingHasAExtendedTypeAsDest = AutoMapper.Mapper.Map <HasAMappingTarget, HasAExtendedUnderlyingType>(testMappingHasAExtendedType); Console.WriteLine(string.Format("the mapping works in both directions when either the dest or src has its property cast '{0}'", testMappingHasAExtendedTypeAsDest.TheHASA.ID == testMappingHasAExtendedType.TheHASATarget.TheID)); }
public static void Examples() { Register(); var original = new HasSingle { ID = 99, Prop = new PropB { ID = 12, Value = "prop b" } }; var copyDest = new Copy();//nothing here //mapping continue down the object graph to terminal valueType nodes unless set explicitly to ignore AutoMapper.Mapper.Map(original, copyDest); //this is false, 'copyDest's Prop is a new object on the heap Console.WriteLine(string.Format("original equals copyDest: {0}", original.Prop.Equals(copyDest.Prop))); HasSingle getAnotherCopy = AutoMapper.Mapper.Map<Copy, HasSingle>(copyDest); //yet another independent copy on the heap with another stack-residing reference Console.WriteLine(string.Format("copy from copy equals original: {0}", getAnotherCopy.Equals(original))); Console.WriteLine(string.Format("copy of copy's properties equal original: {0}", getAnotherCopy.Prop.Equals(original.Prop))); PropA copiedToAnotherType = AutoMapper.Mapper.Map<PropB, PropA>(getAnotherCopy.Prop); Console.WriteLine(string.Format("copy across types with same property name/types {0}", (copiedToAnotherType != null))); //have dealt in the 'Register' the complexities of going from List<PropA> to just PropB //and, likewise, from PropB to List<PropA> so this works as expected and is, again, new //objects on the heap HasList fromTypeToGenericOfType = AutoMapper.Mapper.Map<HasSingle, HasList>(getAnotherCopy); HasSingle fromGenericOfTypeToType = AutoMapper.Mapper.Map<HasList, HasSingle>(fromTypeToGenericOfType); // in "Register" dealt with how to convert ProbValue, PropID from "HasSingle's" Prop property // and, likewise, how to take "HasSingle's" Prop property's ID, Value and copy them over to // "HasValueOfPropB's" top-level value-type properties HasValueOfPropB moveValuesUpObjGraph = AutoMapper.Mapper.Map<HasSingle, HasValueOfPropB>(fromGenericOfTypeToType); HasSingle moveValuesDownObjGraph = AutoMapper.Mapper.Map<HasValueOfPropB, HasSingle>(moveValuesUpObjGraph); PropC primaryPropC = new PropC { ID = 14, Value = "is primary", Primary = true }; PropC secondaryPropC = new PropC { ID = 11, Value = "is secondary", Primary = false }; PropB copiedFromPrimary = AutoMapper.Mapper.Map<PropC, PropB>(primaryPropC); PropB copiedFromSecondary = AutoMapper.Mapper.Map<PropC, PropB>(secondaryPropC); Console.WriteLine("in line ternary operations allowed in mappings {0}", copiedFromPrimary.ID == primaryPropC.ID && copiedFromPrimary.Value == primaryPropC.Value); Console.WriteLine("and resolves on both of the ternary operands {0}", copiedFromSecondary.ID != secondaryPropC.ID && copiedFromSecondary.Value != secondaryPropC.Value); //when a mapping already exist for two types, and some object HAS-A List of one of //those two, the mapping at the object level may operate on the list (using a LINQ expression) //which may override and ternary operations at play on the List's type var ListOfPropC = new List<PropC> { new PropC {ID = 1, Primary = false, Value = "1"},//both the ternary operator and new PropC {ID = 2, Primary = true, Value = "2"},//the Linq expression use this same 'Primary' property new PropC {ID = 3, Primary = false, Value = "3"},//making them exclusive of each other new PropC {ID = 4, Primary = true, Value = "4"} }; HasListWithFlags listWithFlags = new HasListWithFlags { ID = 99, Props = ListOfPropC, Value = "with flags" }; HasList usesDuplexOfMappingRules = AutoMapper.Mapper.Map<HasListWithFlags, HasList>(listWithFlags); Console.WriteLine(string.Format("object copied with duplex of mapping rules {0}", usesDuplexOfMappingRules != null)); Console.WriteLine(string.Format("rules on list applied over rules on type therein {0}", usesDuplexOfMappingRules.Props.Count == 2)); //when the operation on the source is simply to complex to do inline, then define a seperate function //to perform this logic, declare and instantiate a function pointer to it (Func<>) and used it within //the mapping on the source. CopyToHasListWithFlags complexLogicWithinMapping = AutoMapper.Mapper.Map<HasListWithFlags, CopyToHasListWithFlags>(listWithFlags); var functionPtrWasUsed = complexLogicWithinMapping != null; Console.WriteLine(string.Format("the complex mapping returned the dest type {0}", functionPtrWasUsed)); functionPtrWasUsed = complexLogicWithinMapping.Prop != null; Console.WriteLine(string.Format("the complex mapping called the function pointer {0}", functionPtrWasUsed)); var prop = complexLogicWithinMapping.Prop; functionPtrWasUsed = prop.ID == byte.MaxValue && prop.Value == "something special" && prop.Primary; Console.WriteLine(string.Format("and operated as expected {0}", functionPtrWasUsed)); var extendedType = new ExtendsUnderlyingType {ID = 32, ValueOne = "value one", ValueTwo = "value two"}; var testMappingExtendedTypes = AutoMapper.Mapper.Map<UnderlyingType, ExtendedTypesTarget>(extendedType); Console.WriteLine(string.Format("the mapper returned something when given a concrete instance for a map on an Interface '{0}'",testMappingExtendedTypes != null)); Console.WriteLine(string.Format("The value from ID -> TheID is '{0}'",testMappingExtendedTypes.TheID)); var hasAExtendedTypeProp = new HasAExtendedUnderlyingType(); hasAExtendedTypeProp.TopId = 99; hasAExtendedTypeProp.TheHASA = extendedType; var testMappingHasAExtendedType = AutoMapper.Mapper.Map<HasAExtendedUnderlyingType, HasAMappingTarget>(hasAExtendedTypeProp); Console.WriteLine(string.Format("the call to Map did not return null '{0}'", testMappingHasAExtendedType != null)); Console.WriteLine(string.Format("the top level class ID copied fine '{0}'",hasAExtendedTypeProp.TopId == testMappingHasAExtendedType.TheTopID)); Console.WriteLine(string.Format("the child object, the point of this test, also copied '{0}'", testMappingHasAExtendedType.TheHASATarget != null)); Console.WriteLine(string.Format("the child object's ID copied as well '{0}'",testMappingHasAExtendedType.TheHASATarget.TheID == extendedType.ID)); //attempt it in reverse var testMappingHasAExtendedTypeAsDest = AutoMapper.Mapper.Map<HasAMappingTarget, HasAExtendedUnderlyingType>(testMappingHasAExtendedType); Console.WriteLine(string.Format("the mapping works in both directions when either the dest or src has its property cast '{0}'", testMappingHasAExtendedTypeAsDest.TheHASA.ID == testMappingHasAExtendedType.TheHASATarget.TheID)); }