AutoMapper的使用

Posted aofengdaxia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AutoMapper的使用相关的知识,希望对你有一定的参考价值。

什么是AutoMapper?

在多层结构中,经常用到对象到对象的转化,比如数据库Entity到Model的转化,Model和ViewModel的转换,手工去写复制太过麻烦。AutoMapper就是一个可以实现自动转换的类库。
AutoMapper是一个对象与对象的映射器。对象-对象映射通过将一种类型的输入对象转换为不同类型的输出对象来工作。让AutoMapper感兴趣的是,它提供了一些有趣的约定,从而弄清楚如何将类型A映射到类型B.只要类型B遵循AutoMapper建立的约定,映射两种类型几乎就是零配置。

怎么使用Automapper

使用Nuget 直接引用AutoMapper就可以使用AutoMapper了。

对象的字段名称和类型完全一直的方式

AutoMapper.Mapper.Initialize(m => m.CreateMap<Model,ViewModel>(););
var vModel = AutoMapper.Mapper.Map<ViewModel>(modelObj);
var model = AUtoMapper.Mapper.Map<Model>(vModel);

字段名称不完全一致,但是类型一致

public class Book

        public string Title  get; set; 
        public string Note  get; set; 

public class BookViewModel

        public string Title  get; set; 
        public string Desc  get; set; 

AutoMapper.Mapper.Initialize(m => 
                m.CreateMap<Book, BookViewModel>().ForMember(c => c.Note, q =>
                
                    q.MapFrom(z => z.Des);
                );
);

但是上述代码只可以实现DTO,没办法实现OTD

var vBook = Mapper.Map<BookViewModel>(book); //正确
var book = Mapper.Map<BookViewModel>(vBook); //报错

如果要实现反转,需要如下改变:增加.ReverseMap()

AutoMapper.Mapper.Initialize(m => 
                m.CreateMap<Book, BookViewModel>().ForMember(c => c.Note, q =>
                
                    q.MapFrom(z => z.Des);
                ).ReverseMap();
);

字段类型不太一致的,但是有规律的

完全可以自动实现转化Author.Name 和AuthorName的关系

    public class Author
    
        public string Name  get; set; 
    

    public class Book
    
        public string Title  get; set; 
        public Author AuthorName  get; set; 

        public string Note  get; set; 
    
    public class BookViewModel
    
        public string Title  get; set; 

        public string Author get; set; 
        public string Desc  get; set; 
    

类型不一致,名称不符合约定的

    public class Author
    
        public string Name  get; set; 
    

    public class Book
    
        public string Title  get; set; 
        public Author Author  get; set; 

        public string Note  get; set; 
    
    public class BookViewModel
    
        public string Title  get; set; 
        public string Author get; set; 
        public string Desc  get; set; 
    

上面的代码中Author在两处的类型不一样,但是名字并不是按照约定的。那么这样要如何实现呢。

.ForMember(c => c.Author, q =>
                    
                        q.MapFrom(z => z.Author.Name);
                    )

反转的部分和上一步的差不多,总体代码如下。

m.CreateMap<Book, BookViewModel>()
                    .ForMember(c => c.Author, q =>
                    
                        q.MapFrom(z => z.Author.Name);
                    )
                    .ForMember(c => c.Desc, q =>
                
                    q.MapFrom(z => z.Note);
                ).ReverseMap();

但是我们发现反转没成功,需要规定如何反转,修改如下

            AutoMapper.Mapper.Initialize(m =>
            
                m.CreateMap<Book, BookViewModel>()
                    .ForMember(c => c.Author, q =>
                    
                        q.MapFrom(z => z.Author.Name);
                    )
                    .ForMember(c => c.Desc, q =>
                
                    q.MapFrom(z => z.Note);
                ).ReverseMap().ForPath(r => r.Author.Name, q => q.MapFrom(z => z.Author));
            );

当某种类型没办法字段转化是,可以自定义类型转化器

public class Source

    public string Value1  get; set; 
    public string Value2  get; set; 
    public string Value3  get; set; 

public class Source

    public string Value1  get; set; 
    public string Value2  get; set; 
    public string Value3  get; set; 


public void Example()

    Mapper.Initialize(cfg => 
      cfg.CreateMap<string, int>().ConvertUsing(s => Convert.ToInt32(s));
      cfg.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter());
      cfg.CreateMap<string, Type>().ConvertUsing<TypeTypeConverter>();
      cfg.CreateMap<Source, Destination>();
    );
    Mapper.AssertConfigurationIsValid();

    var source = new Source
    
        Value1 = "5",
        Value2 = "01/01/2000",
        Value3 = "AutoMapperSamples.GlobalTypeConverters.GlobalTypeConverters+Destination"
    ;

    Destination result = Mapper.Map<Source, Destination>(source);
    result.Value3.ShouldEqual(typeof(Destination));


public class DateTimeTypeConverter : ITypeConverter<string, DateTime>

    public DateTime Convert(string source, DateTime destination, ResolutionContext context)
    
        return System.Convert.ToDateTime(source);
    


public class TypeTypeConverter : ITypeConverter<string, Type>

    public Type Convert(string source, Type destination, ResolutionContext context)
    
          return Assembly.GetExecutingAssembly().GetType(source);
    

只需要继承这个接口

public interface ITypeConverter<in TSource, TDestination>

    TDestination Convert(TSource source, TDestination destination, ResolutionContext context);

大多数的时候,我们只需要在用到对象的时候使用var obj = Mapper.Map(source)来实现即可,注册和配置可以集中化的管理,或者使用依赖注入。

我只能简单的讲解下我的理解。还有很多部分,需要你来亲自体验:
下面有非常不错的,原文翻译,可以挨着敲敲代码
http://blog.csdn.net/wulex/article/category/6408862

以上是关于AutoMapper的使用的主要内容,如果未能解决你的问题,请参考以下文章

如何在 .NetCore 中使用 AutoMapper 高级功能

.NET Core中使用AutoMapper

AutoMapper的使用

为啥 Automapper 使用这么多内存?

AutoMapper的介绍与使用

0.AutoMapper