AutoMapper官方文档(十二)【自定义值解析器】

尽管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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AutoMapper是一个用于对象映射的开源库。它可以帮助简化对象之间的转换过程,减少手动编写重复的代码。通过配置映射规则,AutoMapper可以自动将一个对象的属性复制到另一个对象中对应的属性上,而不需要手动逐个属性进行赋。 使用AutoMapper,你可以定义映射规则,包括源类型和目标类型以及它们之间的属性映射关系。一旦配置好映射规则,你可以使用简单的API将源对象映射到目标对象上。 以下是一个使用AutoMapper的示例: ```csharp // 定义源类型和目标类型 public class SourceObject { public string Name { get; set; } public int Age { get; set; } } public class DestinationObject { public string Name { get; set; } public int Age { get; set; } } // 配置映射规则 var config = new MapperConfiguration(cfg => { cfg.CreateMap<SourceObject, DestinationObject>(); }); // 创建映射器 var mapper = config.CreateMapper(); // 创建源对象 var source = new SourceObject { Name = "John", Age = 30 }; // 使用映射器进行对象映射 var destination = mapper.Map<SourceObject, DestinationObject>(source); // 输出目标对象属性 Console.WriteLine(destination.Name); // 输出:John Console.WriteLine(destination.Age); // 输出:30 ``` 通过使用AutoMapper,你可以简化对象之间的映射过程,提高开发效率。它支持各种复杂的映射场景,并且可以通过自定义转换器来处理更复杂的映射逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值