AutoMapper:映射 ImmutableHashSet 的问题
AutoMapper: Issues mapping an ImmutableHashSet
我正在尝试使用 AutoMapper
.[=52= Map
和 ReverseMap
ImmutableHashSet
属性 到 ICollection
]
Automapper 成功地将 ImmutableHashSet
属性 映射到 ICollection
,但未能将 ICollection
映射回 ImmutableHashSet
这是最小的可重现示例:
考虑我有 Order
和 OrderItem
class 如下:
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; }
}
Order
和OrderItem
classes需要映射到下面的OrderDto
和classes
public class OrderDto
{
public ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItemDto
{
public int OrderId { get; set; }
public string OrderName { get; set; }
}
下面的 OrderProfile
class 定义了将 Order
映射到 OrderDto
的 Automapper 配置文件,反之亦然。
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; }
}
映射和反向映射 Order
和 OrderDto
class 的代码:
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);
}
从 OrderDto
映射 Order
object
时,出现以下异常:
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 )
非常感谢任何有助于解决此问题的指示。
更新
我以某种方式通过自定义Converter
让它工作。但我真的不知道它是如何工作的。我更新了我的映射器配置如下:
var mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new OrderProfile());
cfg.CreateMap(typeof(ICollection<>), typeof(ImmutableHashSet<>)).ConvertUsing(typeof(HashMapConverter<,>));
}).CreateMapper();
我的HashMapConverter
class:
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
。我原以为 Count
为 0,因为我返回的是一个空的 HashSet
。我怀疑它正在工作,因为 OrderItem
和 OrderItemDto
也通过 AutoMapper
.
映射
我想证实我的假设并知道这是否是一个正确的方法。
在我的类似示例中,我没有得到期望值,而是一个空集合,因此您最好使用
完成转换函数
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;
}
}
而不是返回空;
事实证明,将 ImmutableHashSet
映射到集合并不像看起来那么简单。然而,这让我意识到也许我没有解决正确的问题。我只想确保我的 OrderItem
HashSet
不能在 Order
class 之外被修改。我可以通过返回 IReadOnlyCollection
轻松实现这一点。
这是我更新的 Order
class:
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
class.
之外调用 order.OrderItems.Add(orderItem)
方法
我正在尝试使用 AutoMapper
.[=52= Map
和 ReverseMap
ImmutableHashSet
属性 到 ICollection
]
Automapper 成功地将 ImmutableHashSet
属性 映射到 ICollection
,但未能将 ICollection
映射回 ImmutableHashSet
这是最小的可重现示例:
考虑我有 Order
和 OrderItem
class 如下:
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; }
}
Order
和OrderItem
classes需要映射到下面的OrderDto
和classes
public class OrderDto
{
public ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItemDto
{
public int OrderId { get; set; }
public string OrderName { get; set; }
}
下面的 OrderProfile
class 定义了将 Order
映射到 OrderDto
的 Automapper 配置文件,反之亦然。
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; }
}
映射和反向映射 Order
和 OrderDto
class 的代码:
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);
}
从 OrderDto
映射 Order
object
时,出现以下异常:
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 )
非常感谢任何有助于解决此问题的指示。
更新
我以某种方式通过自定义Converter
让它工作。但我真的不知道它是如何工作的。我更新了我的映射器配置如下:
var mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new OrderProfile());
cfg.CreateMap(typeof(ICollection<>), typeof(ImmutableHashSet<>)).ConvertUsing(typeof(HashMapConverter<,>));
}).CreateMapper();
我的HashMapConverter
class:
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
。我原以为 Count
为 0,因为我返回的是一个空的 HashSet
。我怀疑它正在工作,因为 OrderItem
和 OrderItemDto
也通过 AutoMapper
.
我想证实我的假设并知道这是否是一个正确的方法。
在我的类似示例中,我没有得到期望值,而是一个空集合,因此您最好使用
完成转换函数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;
}
}
而不是返回空;
事实证明,将 ImmutableHashSet
映射到集合并不像看起来那么简单。然而,这让我意识到也许我没有解决正确的问题。我只想确保我的 OrderItem
HashSet
不能在 Order
class 之外被修改。我可以通过返回 IReadOnlyCollection
轻松实现这一点。
这是我更新的 Order
class:
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
class.
order.OrderItems.Add(orderItem)
方法