Dictionary <string,string>使用Automapper </string,string>映射到对象

时间:2011-09-05 16:16:37

标签: c# asp.net-mvc asp.net-mvc-3 dictionary automapper

以下代码仅适用于此问题

我正在上课

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

我有一本像

这样的词典
Dictionary<string,string> data= new Dictionary<string,string>(); 
data.Add("Name","Rusi");
data.Add("Age","23");

User user= new User();

现在,我想使用Userdictionary对象映射到此Automapper。 Automapper映射对象的属性,但在我的例子中有一个字典和对象。

所以,请建议我怎么做呢

6 个答案:

答案 0 :(得分:23)

AutoMapper在对象的属性之间进行映射,并且不应该在这种情况下运行。在这种情况下,你需要反射魔法。您可以通过中间序列化作弊:

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));

如果你坚持使用AutoMapper,你可以做一些类似的事情:

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

然后:

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

如果您需要使用子对象处理更复杂的对象层次结构,您必须问自己以​​下问题:Dictionary<string, string>在这种情况下使用正确的数据结构吗?

答案 1 :(得分:5)

AutoMapper是一个非常灵活的解决方案。您可以使用自定义映射配置文件来实现此目的,例如:

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"] };
    }
  }
}

有了这个,我可以创建一个mapper的自定义实例:

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

config.AssertConfigurationIsValid();

var mapper = new MappingEngine(config);

我可以做的事情:

var dict = new Dictionary<string, string> { { "Name", "Matt" }, { "Age", "27" } };
var user = mapper.Map<User, Dictionary<string, string>>(dict);

答案 2 :(得分:3)

由于我偶然发现了这个问题,我想在当前版本的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

答案 3 :(得分:2)

该线程有些旧,但是如今,如官方documentation所述,如何在自动映射器上无需任何配置即可执行此操作:

  

AutoMapper可以与动态对象进行映射,而无需任何显式配置(...)。类似地,您可以直接从Dictionary映射到对象,AutoMapper会将键与属性名称对齐。

更新

以下代码显示了一个有效的示例(带有单元测试)。

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; }
}

答案 4 :(得分:1)

更简单的解决方案。只需从KeyValuePair映射您的对象。例如:

const noEjsCss = /^(?!.*\.(?:css|ejs)$).*/;

let requireContext = require.context('../scripts', true, noEjsCss);

答案 5 :(得分:0)

如果您的函数类型为“ 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"]));

让我知道是否有帮助。