使用AutoMapper +依赖注入进行映射时访问目标属性(非类型)

时间:2019-02-26 13:23:00

标签: c# automapper

我处于一种非常有趣的情况,我需要AutoMapper能够将对象从类型TSource映射到TDestination,并具有以下限制:

  1. 在映射期间,我需要访问IServiceProvider提供的服务(或更确切地说,是从依赖项注入器提供的服务)。
  2. 我的映射功能需要知道目标对象上的映射属性。这意味着我不需要知道目标属性的类型为string,但是在映射类型上该属性称为NameAddress。这样做的原因是,我需要能够访问该属性的属性。

通过使用自定义值解析器或值转换器,可以很方便地解决不方便的第一个约束。

public class MyValueResolver<TSource, TDestination> 
    : IValueResolver<TSource, TDestination, string>
{
    private readonly ISomeService _someService;

    public MyValueResolver(ISomeService someService)
    {
        _someService = someService;
    }

    public string Resolve(TSource source, TDestination destination, 
        string destMember, ResolutionContext context)
    {
        string result;

        // Perform some complex logic with _someService and attributes of
        // the target property...

        return result;
    }
}

但是我不知道如何知道解析器在目标对象上映射的属性。是否可以在Resolve(source, dest, member, context)方法中检索此信息?

我们正在ASP.NET Core中使用AutoMapper的最新版本。

1 个答案:

答案 0 :(得分:1)

我能够通过使用自定义IValueConverter而不是IValueResolver解决我的问题。转换器使我可以在映射过程中传递一些数据,也可以传递具有多个内容的新对象:

public class MyValueConverter<TSource> : IValueConverter<KeyValuePair<TSource, MemberInfo>, string>
{
    private readonly ISomeService _someService;

    public MyValueConverter(ISomeService someService)
    {
        _someService = someService;
    }

    public string Convert(KeyValuePair<TSource, MemberInfo> data, ResolutionContext context)
    {
        var source = data.Key;
        var targetProperty = data.Value;

        string result;

        // Perform some complex logic with _someService and attributes of
        // the target property...

        return result;
    }
}

为简单起见,在示例中,我选择传递一个简单的KeyValuePair来支持自定义对象,但是两者都可以。可以使用以下方法调用该方法:

CreateMap<MyEntity, MyEntityViewModel>()
    .ForMember(dest => dest.Action, opts => 
        opts.ConvertUsing<MyValueConverter<TEntity>, KeyValuePair<TEntity, MemberInfo>>(src => 
            KeyValuePair.Create(src, opts.DestinationMember)));