Dictionary map to an object using Automapper

前端 未结 6 540
执笔经年
执笔经年 2020-11-29 07:50

Below code is just for this question

I am having a class like

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


        
相关标签:
6条回答
  • 2020-11-29 08:03

    Much simpler solution. Just map your object from KeyValuePair. Example:

    CreateMap<KeyValuePair<Guid, string>, User>()
                .ForMember(u => u.Id, src => src.MapFrom(x => x.Key))
                .ForMember(u => u.Name, src => src.MapFrom(x => x.Value));
    
    0 讨论(0)
  • 2020-11-29 08:09

    As I've just stumbled upon this question I'd like to add this answer possible with the current version of AutoMapper (even if the original question is already pretty old):

    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
    
    0 讨论(0)
  • 2020-11-29 08:09

    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; }
    }
    
    0 讨论(0)
  • 2020-11-29 08:12

    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);
    
    0 讨论(0)
  • 2020-11-29 08:22

    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?

    0 讨论(0)
  • 2020-11-29 08:23

    This will work if your function type is "ExpandoObject".

    public EmpClass
    {
       public string EmpName { get; set; }
       public int EmpId { get; set; }
    }
    
    this.CreateMap<IDictionary<string, object>, EmpClass>()
                    .ForMember(dest => dest.EmpName, src => src.MapFrom(x => x["EmpName"]))
                    .ForMember(dest => dest.EmpId, src => src.MapFrom(x => x["EmpId"]));
    

    Let me know if it helps.

    0 讨论(0)
提交回复
热议问题