AutoMapper官方文档(十二)【自定义值解析器】
2017-11-28 16:18
393 查看
尽管
无论出于何种原因,我们希望
一旦我们有了我们的
在下面的例子中,我们将使用第一个选项,通过泛型告诉
尽管目标成员(
如果我们不关心我们的值解析器中的源/目标类型,或者想要在映射上重用它们,我们可以使用
如果我们不希望
将键值对传递给
在调用映射时,可以使用键值传递额外的对象,并使用自定义解析器从上下文获取对象。
这是如何设置这个自定义解析器的映射
AutoMapper覆盖了不少目的地成员的映射场景,但有1%到5%的目标值需要一些帮助来解决。 很多时候,这个自定义的价值决议逻辑是领域逻辑,可以直接在我们的领域。 但是,如果这个逻辑仅仅涉及到映射操作,就会把我们的源类型弄乱,造成不必要的行为。 在这些情况下,
AutoMapper允许为目标成员配置自定义值解析器。例如,我们可能想要在映射期间计算一个值:
public class Source { public int Value1 { get; set; } public int Value2 { get; set; } } public class Destination { public int Total { get; set; } }
无论出于何种原因,我们希望
Total是源值属性的总和。 由于其他原因,我们不能或不应该把这个逻辑放在我们的
Source类型上。为了提供自定义的值解析器,我们需要先创建一个实现
IValueResolver的类型:
public interface IValueResolver<in TSource, in TDestination, TDestMember> { TDestMember Resolve(TSource source, TDestination destination, TDestMember destMember, ResolutionContext context); }
ResolutionContext包含当前解析操作的所有上下文信息,例如源类型,目标类型,源值等。 一个示例实现:
public class CustomResolver : IValueResolver<Source, Destination, int> { public int Resolve(Source source, Destination destination, int member, ResolutionContext context) { return source.Value1 + source.Value2; } }
一旦我们有了我们的
IValueResolver实现,我们将需要告诉
AutoMapper在解析特定的目标成员时使用这个自定义的值解析器。 我们有几个选项告诉
AutoMapper一个自定义的值解析器使用,包括:
ResolveUsing<TValueResolver> ResolveUsing(typeof(CustomValueResolver)) ResolveUsing(aValueResolverInstance)
在下面的例子中,我们将使用第一个选项,通过泛型告诉
AutoMapper自定义的解析器类型:
Mapper.Initialize(cfg => cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Total, opt => opt.ResolveUsing<CustomResolver>()); Mapper.AssertConfigurationIsValid(); var source = new Source { Value1 = 5, Value2 = 7 }; var result = Mapper.Map<Source, Destination>(source); result.Total.ShouldEqual(12);
尽管目标成员(
Total)没有任何匹配的源成员,但指定自定义解析程序使配置有效,因为解析程序现在负责为目标成员提供值。
如果我们不关心我们的值解析器中的源/目标类型,或者想要在映射上重用它们,我们可以使用
“object”作为源/目标类型:
public class MultBy2Resolver : IValueResolver<object, object, int> { public int Resolve(object source, object dest, int destMember, ResolutionContext context) { return destMember * 2; } }
自定义构造函数方法
由于我们只将自定义解析器的类型提供给AutoMapper,所以映射引擎将使用反射来创建值解析器的实例。
如果我们不希望
AutoMapper使用反射来创建实例,我们可以直接提供它:
Mapper.Initialize(cfg => cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Total, opt => opt.ResolveUsing(new CustomResolver()) );
AutoMapper将使用该特定对象,在解析器可能具有构造函数参数或需要由IoC容器构造的场景中很有用。
自定义提供给解析器的源值
默认情况下,AutoMapper将源对象传递给解析器。 这限制了解析器的可重用性,因为解析器被耦合到源类型。 但是,如果我们提供跨多种类型的通用解析器,我们将
AutoMapper配置为重定向提供给解析器的源值,并使用不同的解析器接口,以便我们的解析器可以使用源/目标成员:
Mapper.Initialize(cfg => { cfg.CreateMap<Source, Destination>() .ForMember(dest => dest.Total, opt => opt.ResolveUsing<CustomResolver, decimal>(src => src.SubTotal)); cfg.CreateMap<OtherSource, OtherDest>() .ForMember(dest => dest.OtherTotal, opt => opt.ResolveUsing<CustomResolver, decimal>(src => src.OtherSubTotal)); }); public class CustomResolver : IMemberValueResolver<object, object, decimal, decimal> { public decimal Resolve(object source, object destination, decimal sourceMember, decimal destinationMember, ResolutionContext context) { //逻辑在这里 } }
将键值对传递给Mapper
在调用映射时,可以使用键值传递额外的对象,并使用自定义解析器从上下文获取对象。Mapper.Map<Source, Dest>(src, opt => opt.Items["Foo"] = "Bar");
这是如何设置这个自定义解析器的映射
Mapper.CreateMap<Source, Dest>() .ForMember(d => d.Foo, opt => opt.ResolveUsing((src, dest, destMember, res) => res.Context.Options.Items["Foo"]));
ForPath
与ForMember相似,从6.1.0开始有
ForPath。
相关文章推荐
- AutoMapper官方文档(十一)【自定义类型转换器】
- Emmet(Zen Coding)官方文档 之六 自定义 Emmet
- ABP官方文档(十二)【时间与时区设置】
- Objective-c官方文档 怎么自定义类
- 自定义 Windows Presentation Foundation 的控件---官方文档
- 【AutoMapper官方文档】DTO与Domin Model相互转换(中)
- AutoMapper官方文档(二)【升级指南】
- Objective-c官方文档 怎么自定义类
- Autofac官方文档(十二)【实例范围】
- 【AutoMapper官方文档】DTO与Domin Model相互转换(下)
- AutoMapper官方文档(十三)【值转换器,Null替换,Map行为前后】
- Emmet(Zen Coding)官方文档 之六 自定义 Emmet
- AutoMapper在MVC中的运用03-字典集合、枚举映射,自定义解析器
- iOS自定义导航栏navigationBar的那些坑--总结自苹果官方文档
- ECharts官方教程(十二)【自定义系列】
- Spring 4 官方文档学习(十二)View技术
- Extjs4 官方文档翻译系列二:组件(components)、自定义组件
- Python3.2官方文档翻译--异常抛出和自定义异常
- Dojo1.11官方教程文档翻译(5.9)创建自定义widget
- django 1.8 官方文档翻译: 2-5-7 自定义查找