Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionary <string,string> map to an object using Automapper

Tags:

I have a class like

public User class
{
 public string Name{get;set;}
 public string Age{get;set;
}

With a dictionary like

Dictionary<string,string> data= new Dictionary<string,string>(); 
data.Add("Name","Rusi");
data.Add("Age","23");

User user= new User();

Now i want to map User object to this dictionary using Automapper. Automapper maps properties of objects but in my case there is a dictionary and object.

How can this be mapped?

like image 943
Rusi Nova Avatar asked Sep 05 '11 16:09

Rusi Nova


People also ask

How do I use AutoMapper to list a map?

Once you have your types, and a reference to AutoMapper, you can create a map for the two types. Mapper. CreateMap<Order, OrderDto>(); The type on the left is the source type, and the type on the right is the destination type.

Can AutoMapper map collections?

Polymorphic element types in collectionsAutoMapper supports polymorphic arrays and collections, such that derived source/destination types are used if found.

Where is AutoMapper used?

AutoMapper is used whenever there are many data properties for objects, and we need to map them between the object of source class to the object of destination class, Along with the knowledge of data structure and algorithms, a developer is required to have excellent development skills as well.

How do you implement AutoMapper?

Open startup. cs class file, add “services. AddAutoMapper(typeof(Startup))” in configure services method. Now the AutoMapper Package was installed and configured in our project.


4 Answers

AutoMapper maps between properties of objects and is not supposed to operate in such scenarios. In this case you need Reflection magic. You could cheat by an intermediate serialization:

var data = new Dictionary<string, string>();
data.Add("Name", "Rusi");
data.Add("Age", "23");
var serializer = new JavaScriptSerializer();
var user = serializer.Deserialize<User>(serializer.Serialize(data));

And if you insist on using AutoMapper you could for example do something along the lines of:

Mapper
    .CreateMap<Dictionary<string, string>, User>()
    .ConvertUsing(x =>
    {
        var serializer = new JavaScriptSerializer();
        return serializer.Deserialize<User>(serializer.Serialize(x));
    });

and then:

var data = new Dictionary<string, string>();
data.Add("Name", "Rusi");
data.Add("Age", "23");
var user = Mapper.Map<Dictionary<string, string>, User>(data);

If you need to handle more complex object hierarchies with sub-objects you must ask yourself the following question: Is Dictionary<string, string> the correct data structure to use in this case?

like image 71
Darin Dimitrov Avatar answered Oct 01 '22 01:10

Darin Dimitrov


This thread is a bit old, but nowadays there's how to do it on automapper without any configuration, as stated at official documentation:

AutoMapper can map to/from dynamic objects without any explicit configuration (...) Similarly you can map straight from Dictionary to objects, AutoMapper will line up the keys with property names.

Update:

The following code shows a working sample (with unit tests).

void Test()
{
    var mapper = new MapperConfiguration(cfg => { }).CreateMapper();
    var dictionary = new Dictionary<string, object>()
    {
        { "Id", 1 },
        { "Description", "test" }
    };

    var product = mapper.Map<Product>(dictionary);

    Assert.IsNotNull(product);
    Assert.AreEqual(product.Id, 1);
    Assert.AreEqual(product.Description, "test");
}

class Product
{
    public int Id { get; set; }
    public string Description { get; set; }
}
like image 41
Marcos Jonatan Suriani Avatar answered Oct 01 '22 01:10

Marcos Jonatan Suriani


With the current version of AutoMapper:

public class MyConfig
{
    public string Foo { get; set; }
    public int Bar { get; set; }
}
var config = new MapperConfiguration(cfg => {});
var mapper = config.CreateMapper();

var source = new Dictionary<string, object>
{
    ["Foo"] = "Hello",
    ["Bar"] = 123
};
var obj = mapper.Map<MyConfig>(source);
obj.Foo == "Hello"; // true
like image 9
mkuckert Avatar answered Sep 30 '22 01:09

mkuckert


AutoMapper is quite a flexible solution. You could probably achieve this using a custom mapping profile, e.g.:

public class UserMappingProfile : Profile
{
  // Props
  public override string ProfileName { get { return "UserMappingProfile"; } }

  // Methods
  public override void Configure()
  {
    CreateMap<User, Dictionary<string, string>>().ConvertUsing<DictionaryTypeConverter>();
    base.Configure();
  }

  // Types
  internal class DictionaryTypeConverter : ITypeConverter<User, Dictionary<string, string>>
  {
    public User Convert(ResolutionContext context)
    {
      var dict = context.SourceValue as Dictionary<string, string>;
      if (dict == null)
        return null;

      return new User() { Name = dict["Name"], Age = dict["Age"] };
    }
  }
}

With this, I can create a custom instance of a mapper:

var config = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
config.AddProfile<UserMappingProfile>();

config.AssertConfigurationIsValid();

var mapper = new MappingEngine(config);

Which I could probably do:

var dict = new Dictionary<string, string> { { "Name", "Matt" }, { "Age", "27" } };
var user = mapper.Map<User, Dictionary<string, string>>(dict);
like image 7
Matthew Abbott Avatar answered Sep 29 '22 01:09

Matthew Abbott