2

我正在尝试将属性分配给Mapusing 。ReverseMapImmutableHashSetICollectionAutoMapper

Automapper 成功将ImmutableHashSet属性映射到,ICollection但无法将其映射ICollectionImmutableHashSet

这是最小的可重现示例:

考虑我有 Order如下OrderItem课程:

public class Order
{
    private HashSet<OrderItem> _orderItems;

    public Order()
    {
        _orderItems = new HashSet<OrderItem>();
    }

    public ImmutableHashSet<OrderItem> OrderItems
    {
        get => _orderItems.ToImmutableHashSet();
        private set => _orderItems = value.ToHashSet();
    }

    public void AddOrderItem(OrderItem orderItem)
    {
        _orderItems.Add(orderItem);
    }

    public void RemoveOrderItem(OrderItem orderItem)
    {
        _orderItems.Add(orderItem);
    }
}

public class OrderItem
{
    public OrderItem(int orderId, string orderName)
    {
        OrderId = orderId;
        OrderName = orderName;
    }

    public int OrderId { get; private set; }


    public string OrderName { get; private set; }
}

OrderOrderItem类需要映射到下面的和OrderDto

public class OrderDto
{
    public ICollection<OrderItem> OrderItems { get; set; }
}

public class OrderItemDto
{

    public int OrderId { get; set; }


    public string OrderName { get; set; }
}

下面的类定义要映射到OrderProfile的 Automapper 配置文件,反之亦然。OrderOrderDto

public class OrderProfile : Profile
{
    public OrderProfile()
    {
        CreateMap<Order, OrderDto>()
            .ReverseMap();
        CreateMap<OrderItem, OrderItemDto>()
            .ReverseMap();
    }
}

public class OrderItemDto
{

    public int OrderId { get; set; }


    public string OrderName { get; set; }
}

映射和反向映射OrderOrderDto类的代码:

private static void Map()
{
    var mapper = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile(new OrderProfile());
    }).CreateMapper();

    var order = new Order();
    order.AddOrderItem(new OrderItem(1, "Laptop"));
    order.AddOrderItem(new OrderItem(2, "Keyboard"));

    // This code maps correctly
    var orderDto = mapper.Map<OrderDto>(order);

    // This is where I get an exception
    var orderMappedBack = mapper.Map<Order>(orderDto);
}

在映射Order objectfromOrderDto时,我得到以下异常:

System.ArgumentException: System.Collections.Immutable.ImmutableHashSet`1[ReadOnlyCollectionDemo.OrderItem]
needs to have a constructor with 0 args or only optional args.
(Parameter 'type') at lambda_method(Closure , OrderDto , Order , ResolutionContext )

非常感谢任何有助于解决此问题的指针。

更新

我以某种方式让它通过 custom 工作Converter。但我真的不知道它是如何工作的。我更新了我的映射器配置如下:

 var mapper = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(new OrderProfile());
            cfg.CreateMap(typeof(ICollection<>), typeof(ImmutableHashSet<>)).ConvertUsing(typeof(HashMapConverter<,>));
        }).CreateMapper();

我的HashMapConverter班级:

public class HashMapConverter<TCollection, TImmutableHashSet> 
        : ITypeConverter<ICollection<TCollection>, ImmutableHashSet< TImmutableHashSet>>
    {
        public ImmutableHashSet< TImmutableHashSet> Convert(
            ICollection<TCollection> source,
            ImmutableHashSet< TImmutableHashSet> destination,
            ResolutionContext context)
        {
            return ImmutableHashSet<TImmutableHashSet>.Empty;
        }
    }

正如你所看到的,我只是返回一个空的ImmutableHashSet,然而,令我惊讶的OrderDto是,它现在已成功映射回Order正确数量的OrderItems Count. 我本来希望Count0 因为我返回一个空的HashSet。我怀疑它正在工作,因为OrderItem并且OrderItemDto也通过AutoMapper.

我想确认我的假设并知道这是否是正确的方法。

4

2 回答 2

2

在我类似的例子中,我没有得到预期值而是一个空集合,所以你最好完成转换函数

public class HashMapConverter<TCollection, TImmutableHashSet>
: ITypeConverter<ICollection<TCollection>, ImmutableHashSet<TImmutableHashSet>>
{
    public ImmutableHashSet<TImmutableHashSet> Convert(
        ICollection<TCollection> source,
        ImmutableHashSet<TImmutableHashSet> destination,
        ResolutionContext context)
    {
        var hs =new HashSet<TCollection>(source);
        return ((IEnumerable<TImmutableHashSet>)hs).ToImmutableHashSet<TImmutableHashSet>();
        //return ImmutableHashSet<TImmutableHashSet>.Empty;
    }
}

而不是返回空;

于 2020-05-06T09:44:49.597 回答
0

事实证明,将 anImmutableHashSet与集合映射并不像看起来那么简单。然而,这让我意识到,也许我没有解决正确的问题。我想要的只是确保OrderItem HashSet不能在Order课堂外修改我的。我可以通过返回一个IReadOnlyCollection.

这是我更新的Order课程:

public class Order
{
    private HashSet<OrderItem> _orderItems;

    public Order()
    {
        _orderItems = new HashSet<OrderItem>();
    }

    public IReadOnlyCollection<OrderItem> OrderItems
    {
        get => _orderItems.ToImmutableHashSet();
        private set => _orderItems = value.ToHashSet();
    }

    public void AddOrderItem(OrderItem orderItem)
    {
        _orderItems.Add(orderItem);
    }

    public void RemoveOrderItem(OrderItem orderItem)
    {
        _orderItems.Add(orderItem);
    }
}

IReadOnlyCollection不仅可以帮助我解决 Automapper 问题,而且除此之外,它不会公开该Add方法。因此,用户不能意外调用类order.OrderItems.Add(orderItem)外的方法Order

于 2020-05-11T21:17:27.937 回答