AgileMapper has extensive support for mapping to and from Dictionaries. Out of the box:
- Only dictionaries with string keys are supported
- Dictionary keys must match target member names exactly, ignoring case (configurable)
- Parent and child member names are matched to dictionary keys separated with a dot (configurable), or flattened - with no separator
- Enumerable elements are matched to dictionary keys by their index inside square brackets (configurable)
- Dictionaries can contain all or a mixture of value type values, collections and complex types - anything with a matching key is used
- Target members with no matching key in the dictionary are ignored
For example, the following target type:
public class ContactDetails
{
public string Name { get; set; }
public string[] PhoneNumbers { get; set; }
public IEnumerable<Address> Addresses { get; set; }
}
public class Address
{
public int HouseNumber { get; set; }
public string StreetName { get; set; }
}
...can be mapped from the following source dictionary:
var source = new Dictionary<string, string>
{
["Name"] = "Steve",
["PhoneNumbers[0]"] = "01234 567890",
["PhoneNumbers[1]"] = "07890 654321",
["PhoneNumbers[2]"] = "01234 987654",
["Addresses[0].HouseNumber"] = "123",
["Addresses[0]StreetName"] = "Dictionary Street"
};
var contactDetails = Mapper.Map(source).ToANew<ContactDetails>();
The created contactDetails
will have the following property values:
Name
set to 'Steve'PhoneNumbers
set to a new, 3-element string array containing:- "01234 567890"
- "07890 654321" and
- "01234 987654"
Addresses
set to a new, 1-elementList<Address>
containing anAddress
:- With
HouseNumber
set to '123' (parsed from the string) - With
StreetName
set to "Dictionary Street"
- With
Note that the StreetName
key had no separator, but the mapping works anyway.
The following source ContactDetails
:
var source = new ContactDetails
{
Name = "Bob",
PhoneNumbers = new[] { "01234 567890", "07890 123456" },
Addresses = new[]
{
new Address { HouseNumber = 123, StreetName = "My Street" },
new Address { HouseNumber = 456, StreetName = "Your Street" }
}
};
...can be mapped to a dictionary:
var dictionary = Mapper.Map(source).ToANew<Dictionary<string, object>>();
// or:
var dictionaryInterface = Mapper.Map(source).ToANew<IDictionary<string, object>>();
The created Dictionary
will have the following keys and values:
"Name"
set to "Bob""PhoneNumbers[0]"
set to "01234 567890""PhoneNumbers[1]"
set to "07890 123456""Addresses[0].HouseNumber"
set to 123"Addresses[0].StreetName"
set to "My Street""Addresses[1].HouseNumber"
set to 456"Addresses[1].StreetName"
set to "Your Street"
Dictionary mapping is highly configurable.