替换 Automapper 的 ForAllOtherMembers()

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

ForAllOtherMembers 扩展方法已从 Automapper 11 中删除 我用它来忽略除前面提到的属性之外的属性的常规映射,如下所示

ForAllOtherMembers(opt=>opt.ignore())

如何在 Automapper 11 中执行此操作?

c# automapper
4个回答
15
投票

我永远不会改变我的代码中的哪怕一行,因为 AutoMapper 的作者认为无论出于什么“原因”,这都不是一件“正确”的事情。

快速而肮脏的解决方案,添加单元测试是有意义的:

using AutoMapper.Internal;
using AutoMapper.Configuration;

public static class AutoMapperExtensions
{
    private static readonly PropertyInfo TypeMapActionsProperty = typeof(TypeMapConfiguration).GetProperty("TypeMapActions", BindingFlags.NonPublic | BindingFlags.Instance);

    // not needed in AutoMapper 12.0.1
    private static readonly PropertyInfo DestinationTypeDetailsProperty = typeof(TypeMap).GetProperty("DestinationTypeDetails", BindingFlags.NonPublic | BindingFlags.Instance);

    public static void ForAllOtherMembers<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression, Action<IMemberConfigurationExpression<TSource, TDestination, object>> memberOptions)
    {
        var typeMapConfiguration = (TypeMapConfiguration)expression;

        var typeMapActions = (List<Action<TypeMap>>)TypeMapActionsProperty.GetValue(typeMapConfiguration);

        typeMapActions.Add(typeMap =>
        {
            var destinationTypeDetails = (TypeDetails)DestinationTypeDetailsProperty.GetValue(typeMap);

            foreach (var accessor in destinationTypeDetails.WriteAccessors.Where(m => typeMapConfiguration.GetDestinationMemberConfiguration(m) == null))
            {
                expression.ForMember(accessor.Name, memberOptions);
            }
        });
    }
}

1
投票

MemberList.None 不会阻止具有相同成员名称的自动映射属性。

我还尝试了一些其他解决方案来查找给定配置文件的映射,并将属性映射更改为忽略未映射的属性名称,但这不起作用,因为属性已被视为已映射。

对我来说这个问题的不幸答案是使用 CustomTypeConverter

public class OrderTypeConverter : ITypeConverter<ThirdPartyOrder, MyOrder>
{
    public Order.Order Convert(ThirdPartyOrder source, MyOrder destination, ResolutionContext context) =>
        new MyOrder()
        {
            id = source.id,
            __type = source.__type,
            company_id = source.company_id,
            stops = source.stops
        };
}

然后

    private readonly OrderTypeConverter orderTypeConverter;

    public OrderProfile()
    {
        this.orderTypeConverter = new OrderTypeConverter();

        this.CreateMap<ThirdPartyOrder, MyOrder>().ConvertUsing(orderTypeConverter);
    }

0
投票

您可以在 CreateMap 调用中进行设置:

CreateMap<TSource, TDest>(MemberList.None)

0
投票

这是一个更新的变体,它使用新的 .NET 8 方法来反射私有成员。对于 .NET 8 目标来说,它的性能应该会更高一些。

using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using AutoMapper.Configuration;

#if NET8_0_OR_GREATER
using System.Runtime.CompilerServices;
#else
using System.Reflection;
#endif

namespace MyNamespace;

public static class AutoMapperExtensions
{
#if NET8_0_OR_GREATER
    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_TypeMapActions")]
    private static extern List<Action<TypeMap>> GetTypeMapActions(TypeMapConfiguration typeMapConfiguration);
#else
    private static readonly PropertyInfo TypeMapActionsProperty = typeof(TypeMapConfiguration).GetProperty("TypeMapActions", BindingFlags.NonPublic | BindingFlags.Instance)!;
#endif

    public static void ForAllOtherMembers<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression, Action<IMemberConfigurationExpression<TSource, TDestination, object>> memberOptions)
    {
        var typeMapConfiguration = (TypeMapConfiguration)expression;

#if NET8_0_OR_GREATER
        var typeMapActions = GetTypeMapActions(typeMapConfiguration);
#else
        var typeMapActions = (List<Action<TypeMap>>)TypeMapActionsProperty.GetValue(typeMapConfiguration)!;
#endif

        typeMapActions.Add(typeMap =>
        {
            var destinationTypeDetails = typeMap.DestinationTypeDetails;

            foreach (var accessor in destinationTypeDetails.WriteAccessors.Where(m => typeMapConfiguration.GetDestinationMemberConfiguration(m) == null))
            {
                expression.ForMember(accessor.Name, memberOptions);
            }
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.