在 Automapper 11 中映射或忽略索引器属性

问题描述 投票:0回答:1

我在版本 11 中使用 AutoMapper 映射两个类时遇到一些问题。目标类具有索引器属性,这会导致问题。

自 Automapper 11 起,索引器属性不再自动被忽略。

出于测试目的,我使用了三个类:

public class Source {}

public class Target {
    public float this[int key]
    {
        get
        {
            return 0;
        }
        set
        {
        }
    }
}

public class MapperProfile: Profile
{
    public MapperProfile()
    {
        CreateMap<Source, Target>();
    }
}

在启动过程中,我调用

mapper.ConfigurationProvider.AssertConfigurationIsValid()
来验证配置。由于未映射的 Item 属性,此操作失败。

虽然可以使用 忽略以 Item

开头的所有属性
this.AddGlobalIgnore("Item")

在配置文件中,我不想使用这种通用方法来忽略它,特别是因为第一个参数被标记为 propertyNameStartingWith - 这对我来说意味着其他属性,例如 ItemWithSuffix 也可能被忽略。

我尝试采用的另一个策略是对属性使用显式忽略。由于编译器错误,使用表达式符号失败:

CreateMap<Source, Target>()
    .ForMember(dest => dest[], opt => opt.Ignore())
    .ReverseMap();

向表达式添加任意索引失败并出现另一个错误,因此这似乎也不是一个可行的解决方案:

CreateMap<Source, Target>()
    .ForMember(dest => dest[0], opt => opt.Ignore())
    .ReverseMap();

在这种情况下,错误指出,我们可能无法映射到子属性。

使用成员名称语法时,会出现一些不同的错误。

CreateMap<Source, Target>()
    .ForMember("Item", opt => opt.Ignore())
    .ReverseMap();

在这种情况下,它会失败并显示以下消息:

为调用方法“Double get_Item(Int32)”(参数“property”)提供的参数数量不正确

使用

[]
Item[]
失败,并显示缺少属性通知。

我采用的最后一个策略是使用 ForAllMembers 调用。这成功了,但是,我想知道是否有更好的解决方案来处理此逻辑,允许对单个成员使用特定的映射逻辑。

CreateMap<Source, Target>()
    .ForAllMembers(x =>
    {
        if (x.DestinationMember.Name == "Item")
        {
            x.Ignore();
        }
    });
automapper automapper-11
1个回答
0
投票

所以我刚才就面临这个问题。我正在使用 .NET 8 和 Automapper 13。

在这个项目的类中,我经常有多个索引属性,并且具有不同的签名。一种通常采用字符串键,一种可能有整数,但它们通常使用枚举。这并不重要——为什么——但要点是一个类可以有多个索引器;它们全部被命名为“物品”。

我只是希望 Automapper 忽略索引器,因为我经常将它们设置为获取封装属性(甚至可能是嵌套类)的快捷方式。

但是,将“Item”添加到全局忽略似乎没有任何效果;至少,它没有解决问题...

这做到了..

new MapperConfiguration(cfg => {

     // array of types with indexers to use in automapper
     Type[] types = [typeof(HasIndexers), typeof(AnotherWithIndexers)];

     // Get list of reflected PropertyTypes to ignore
     var indexers = types.SelectMany(x => 
            x.GetProperties().Where(y => y.Name == "Item")).ToList();
     indexers.ForEach(x => cfg.ShouldMapProperty = x => false);
     
     // Continue with your configuration
     cfg.AddProfile<ProfileType>();
}).CreateMapper();
© www.soinside.com 2019 - 2024. All rights reserved.