Automapper中的参数条件映射

3

我希望能将参数传递给一个映射,以便根据该参数决定一个值。

一个简单的类

public class Person
{
  string Name;
}

以及它的DTO

public class PersonDTO
{
  string Name;
  string IsAProgrammer;
}

我希望您能为我提供类似于这样的功能。
var parameterIsTrue = true; // how do I pass this value?

CreateMap<MyClassDTO, MyClass>()
  .ForMember(x => x.Name, opt => opt.MapFrom(src => src.Name))
  .ForMember(x => x.IsAProgrammer, 
               opt => opt.MapFrom(parameterIsTrue ? "sure!" : "nope"));

编辑

我正在尝试编写自定义解析器,但不知道如何将参数传递给它。我已经 figured out 如何制作解析器:

public class PersonResolver : IValueResolver<Person, PersonDTO, string>
{
  ...
  public string Resolve(Person src, 
                        PersonDTO dest, 
                        string destMember, 
                        ResolutionContext context)
  {
    return (bool) context.Items["isProgrammer"] ? "sure!" : "nope";
  }
}

但是我在映射方面仍然失败了:
CreateMap<MyClassDTO, MyClass>()
  .ForMember(x => x.Name, opt => opt.MapFrom(src => src.Name))
  .ForMember(x => x.IsAProgrammer, 
               opt => opt.ResolveUsing(PersonResolver)); // what ???
               // how do I pass the context?

http://docs.automapper.org/en/latest/Custom-value-resolvers.html#passing-in-key-value-to-mapper - Lucian Bargaoanu
我发现了那个,但我还没有想出如何将其应用于这个例子。 - evilpixi
@evilpixi编写一个接受你的参数的CustomResolver - HariHaran
谢谢,我现在编辑了问题。 - evilpixi
1个回答

0
我找到了一个解决方案,适用于我的使用情况。在某些条件下,我有一个对象的详细信息,我不想加载它。
我创建了这个扩展方法,以便轻松重用所有符合此标准的属性:

/// <summary>
/// Don't map the field if the provided <paramref name="keyName"/> is set to <see cref="false"/>. Defaults to true otherwise
/// </summary>
public static IMemberConfigurationExpression<TSource, TDestination, TMember> 
  IgnoreIfParam<TSource, TDestination, TMember>(
    this IMemberConfigurationExpression<TSource, TDestination, TMember> config, 
    string keyName)
{
    config
        .PreCondition(rc =>
        {
            if (rc.Options.Items.TryGetValue(keyName, out var performMapping) && performMapping is bool b)
            {
                return b;
            }
            return true;
        });
    return config;
}


在您的映射配置文件中,您可以像下面这样使用上述扩展方法:
public const string IncludeDetail = "IncludeDetail";

public MyProfile() {
 CrateMap<Source, Dest>()
    //for a member with a specified MapFrom():
    .ForMember(x => x.Media, c => c.IgnoreIfParam(IncludeProductDetail).MapFrom(x => x.Detail.Media))
    
    //for a member with implied MapFrom() on the source, you don't need MapFrom()
    .ForMember(x => x.Name, c => c.IgnoreIfParam(MyProfile.IncludeDetail))

然后为了在映射时设置这个条件,我创建了另一个帮助扩展方法:

public static IMappingOperationOptions<object, TDestination> 
  SetOption<TDestination>(
    this IMappingOperationOptions<object, TDestination> options, 
    string key, bool val)
{
    options.Items[key] = val;
    return options;
}

然后你可以在映射时这样调用它:

var res = _mapper.Map<MyView>(model, o => o
    .SetOption(MyProfile.IncludeDetail, false)
);
return res;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接