• AutoMapper(四)


    返回总目录


    自定义值解析

    虽然AutoMapper覆盖了相当一部分目标成员的映射场景,但是还有 1-5%的目标值需要解析处理一下。很多时候,自定义的值解析是可以放在领域层的领域逻辑。然而,如果该逻辑只是和映射操作有关的话,那它就会应为一些不必要的行为使得源类型很凌乱。这种场合,AutoMapper允许我们为目标成员配置自定义的值解析器。

    举个栗子,有两个类Source和Destination,定义如下:

    public class Source
    {
        public int Value1 { get; set; }
        public int Value2 { get; set; }
    }
    public class Destination
    {
        public int Total { get; set; } 
    }

    我们想要在映射期间产生一个计算的值,也就是说,在Source到Destination映射的过程中,把Source的两个属性值加起来赋给Destination的属性。由于某些原因,我们不能把这个逻辑放到源类型里,为了提供一个自定义值解析器,我们首先需要创建一个实现了IValueResolver:

    public class MyValueResolver : IValueResolver
    {
    
        public ResolutionResult Resolve(ResolutionResult source)
        {
            //TODO:实现逻辑
        }
    }

    ResolutionContext包含了当前解析操作的所有上下文信息,如源类型,源值等等。大多数场合,我们不需要这个更高级的接口。另一种方法,我们可以实现抽象类ValueResolver<TSource, TDestination>:

    public class MyValueResolver : ValueResolver<Source, int>
    {
    
        protected override int ResolveCore(Source source)
        {
            return source.Value1 + source.Value2;
        }
    }

    现在,我们已经实现了自己的值解析器,接下来就需要告诉AutoMapper,当解析一个特定的目标成员时,要使用这个自定义的值解析器。有3中方式告诉AutoMapper如何使用自定义解析器,包括:

    • ResolveUsing<TValueResolver>
    • ResolveUsing(typeof(CustomValueResolver))
    • ResolveUsing(aValueResolverInstance)

    接下来,我们就开始使用自己的值解析器:

    class Program
    {
        static void Main(string[] args)
        {
            Mapper.CreateMap<Source, Destination>().ForMember(dest => dest.Total, opt =>
            {
                opt.ResolveUsing<MyValueResolver>();
            });
    
            var src = new Source {Value1 = 3, Value2 = 5};
    
            var destObj= Mapper.Map<Destination>(src);
            Console.WriteLine("destObj.Total={0}", destObj.Total);
            Console.Read();
        }
    }

    虽然目标成员Total没有任何匹配的源成员,但是我们给它添加了有效配置的自定义解析器,解析器就会对目标成员值的提供负责。

    测试成功,结果如下:

    image

    自定义构造函数方法

    因为我们只提供了自定义的解析器类型给AutoMapper,所以映射引擎会使用反射创建该值解析器的实例。如果我们不想要AutoMapper使用反射创建实例,我们要么直接提供一个实例,要么使用ConstruceBy方法来提供一个自定义的构造函数方法:

    Mapper.CreateMap<Source, Destination>().ForMember(dest => dest.Total, opt =>
    {
        opt.ResolveUsing<MyValueResolver>().ConstructedBy(()=>new MyValueResolver());
    });

    在映射操作期间,AutoMapper不使用反射,直接执行此回调函数。这在解析器可能需要构造函数参数或者需要通过Ioc容器构建的时候很有用。

    这里不再做演示,有兴趣的小伙伴可自行研究。

  • 相关阅读:
    Java中常见的异常
    WebView中Js与Android本地函数的相互调用
    Gson解析POJO类中的泛型参数
    JAVA反射技术的使用
    Couchbase 找回登录密码
    微信内网页支付开发手记
    Android实现自定义字体
    Android实现图片裁切
    Android实现ExpandableTextView可扩展TextView
    仿美团实现地域选择(二)
  • 原文地址:https://www.cnblogs.com/farb/p/4942170.html
Copyright © 2020-2023  润新知