首页 > 解决方案 > ForAllMembers 覆盖已定义的忽略规则

问题描述

我正在使用AutoMapper,我需要忽略Attribute未定义的成员。然后,如果没有忽略成员,我只需要在定义值的地方进行映射。我已经设法分别实现了这两个,但ForAllMembers/ForAllOtherMembers似乎覆盖了第一条规则。

假设我有这个课程:

public class Foo
{
    [MyCustomAttribute]
    public string Name { get; set; }

    public string IgnoreMe { get; set; }

    [MyCustomAttribute]
    public int? DontIgnoreNumber { get; set; }
}

我想IgnoreMe不管。然后,对于Nameand DontIgnoreNumber,我只想在它们具有值时才映射它们。我怎样才能做到这一点?

我试过这个:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Foo, Foo>()
        .IgnoreAllNonAttributedEntities()
        .ForAllOtherMembers(opts =>
        {
            opts.Condition((src, dest, srcMember) =>
            {
                // Check if source is a default value
                return srcMember != null;
            });
        });
});

我已检查该ForAllOtherMembers规则是否有效。我分别检查了它IgnoreAllNonAttributedEntities是否正常工作。当我尝试将它们结合起来时,ForAllOtherMembers似乎优先考虑。

IgnoreAllNonAttributedEntities定义为:

public static IMappingExpression<TSource, TDestination> IgnoreAllNonAttributedEntities<TSource, TDestination>
    (this IMappingExpression<TSource, TDestination> expression)
{
    var flags = BindingFlags.Public | BindingFlags.Instance;
    //var sourceType = typeof(TSource);
    var destinationType = typeof(TDestination);

    foreach(var prop in destinationType.GetProperties(flags))
    {
        var attr = ReflectionHelpers.GetAttribute<MyCustomAttribute>(prop);
        if (attr == null)
        {
            expression.ForMember(prop.Name, opt => opt.Ignore());
        }
    }

    return expression;
}

标签: c#automapper

解决方案


我刚刚运行了您的代码,它按预期工作。然而,也许困扰你的是 c# 中值类型的默认值(因为你只检查空值)。这是我对值类型的修复:

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Foo, Foo>()
        .IgnoreAllNonAttributedEntities()
        .ForAllOtherMembers(opts =>
        {
            opts.Condition((src, dest, srcMember) =>
            {
                var srcType = srcMember?.GetType();
                if (srcType is null)
                {
                    return false;
                }

                return (srcType.IsClass && srcMember != null)
                || (srcType.IsValueType
                && !srcMember.Equals(Activator.CreateInstance(srcType)));
            });
        });
});

我已经使用 NuGet (8.0.0.0) 上提供的最新版本的自动映射器重新创建了您的场景。


推荐阅读