AutoMapper是干什么用的?
AutoMapper 是一个用在.Net平台上的对象到对象的自动化映射工具。可将一种类型的对象自动转换到另一种类型的对象。
例如将Model对象和DTO对象之间互转操作。
怎么安装使用
可以使用Nuget包工具搜索“AutoMapper”进行安装使用。
官方网站
https://automapper.readthedocs.io/en/latest/Getting-started.html
快速使用
1.配置对象映射关系
2.使用configuration.CreateMapper()生成mapper对象
3.调用mapper.Map(src)方法进行映射。
public class Source
{
public int SomeValue { get; set; }
}
public class Destination
{
public int SomeValue { get; set; }
}
//Configure AutoMapper
var configuration = new MapperConfiguration(
cfg=> {
cfg.CreateMap<Source, Destination>();
});
configuration.AssertConfigurationIsValid();
var mapper = configuration.CreateMapper();
Source source = new Source() { SomeValue = 1 };
Destination destination = mapper.Map<Source, Destination>(source);
Console.WriteLine(destination.SomeValue);
一般在哪对AutoMapper进行配置
一个应用程序只需要配置一次。这就意味着最好的配置地方在应用程序启动的地方,如
对于ASP.NET应用程序来说可以放在Global.asax文件中。
怎么测试(验证)映射
当调用方法configuration.AssertConfigurationIsValid()时,AutoMapper会自动对配置进行验证,如果有异常会在编译时弹出。
忽略目标对象不存在的成员
在配置时,在CreateMap方法中传入MemberList的枚举值进行选择是使用源成员或者None。
cfg.CreateMap<ProductDto, Product>(MemberList.None);
嵌套类对象的映射
例我们有源对象OuterSource,它包含一个子对象InnerSource。我们要映射成一个类似的结构对象,目标OuterDest对象包含一个子对象InnerDest,我们只需要在配置时,将父子对象映射都列出来就行了。如下代码:
ublic class OuterSource
{
public int Value { get; set; }
public InnerSource Inner { get; set; }
}
public class InnerSource
{
public int OtherValue { get; set; }
}
public class OuterDest
{
public int Value { get; set; }
public InnerDest Inner { get; set; }
}
public class InnerDest
{
public int OtherValue { get; set; }
}
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<OuterSource, OuterDest>();
cfg.CreateMap<InnerSource, InnerDest>();
});
config.AssertConfigurationIsValid();
var source = new OuterSource
{
Value = 5,
Inner = new InnerSource {OtherValue = 15}
};
var mapper = config.CreateMapper();
var dest = mapper.Map<OuterSource, OuterDest>(source);
dest.Value.ShouldEqual(5);
dest.Inner.ShouldNotBeNull();
dest.Inner.OtherValue.ShouldEqual(15);
自定义类型转换器
如我们拥有一个类
public class Source
{
public string Value1 { get; set; }
public string Value2 { get; set; }
public string Value3 { get; set; }
}
想转换成的目标类是
public class Destination
{
public int Value1 { get; set; }
public DateTime Value2 { get; set; }
public Type Value3 { get; set; }
}
源类对象的成员类型和目标对象的成员类型是不一致的,我们可以使用如下方法。
[Test]
public void Example()
{
var configuration = new MapperConfiguration(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>();
});
configuration.AssertConfigurationIsValid();
var source = new Source
{
Value1 = "5",
Value2 = "01/01/2000",
Value3 = "AutoMapperSamples.GlobalTypeConverters.GlobalTypeConverters+Destination"
};
var mapper = configuration.CreateMapper();
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 class Source
{
public int Value1 { get; set; }
public int Value2 { get; set; }
public string Other {get;set;
}
public class Destination
{
public int Total { get; set; }
public string OtherOff {get;set;}
}
已知目标对象的成员值Total=Source.Value1+Source.Value2,并且可以发现Source.Other成员名称和Destination.OtherOff成员名称不一致,AutoMapper就不知道该进行如何转换了。
对于第一种情况我们可以需要定义一个值解释器类
public class CustomResolver : IValueResolver<Source, Destination, int>
{
public int Resolve(Source source, Destination destination, int member, ResolutionContext context)
{
return source.Value1 + source.Value2;
}
}
对于第二种情况可以直接使用MapFrom方法就行。代码如下:
var configuration = new MapperConfiguration(cfg =>
cfg.CreateMap<Source, Destination>()
.ForMember(dest => dest.Total, opt => opt.MapFrom<CustomResolver>())
.ForMember(dest => dest.OtherOff, opt => opt.MapFrom(src => src.Other))
);
configuration.AssertConfigurationIsValid();
var source = new Source
{
Value1 = 5,
Value2 = 7,
Other = "ni"
};
var mapper = configuration.CreateMapper();
var result = mapper.Map<Source, Destination>(source);
result.Total.ShouldEqual(12);
注意事项
源和目标的名称尽量保持一致,否则就需要自己进行配置说明。
更多
AutoMapper还有很多强大并且实用的功能,如自动快速扁平化对象等,去官网发现吧。