如何使用AutoMapper将具有多个通用列表的对象映射到具有相应非泛型列表的另一个对象?

Aar*_*mer 6 f# automapper

我创建了一个ListTypeConverter:

type ListTypeConverter<'source, 'destination>() =
    interface ITypeConverter<'source list, Proxies.List> with
        member this.Convert(source, destination, context) =
            let proxyList = new Proxies.List()
            source 
            |> List.map(fun item -> _mapper.Map<'source, 'destination>(item))
            |> List.iter(fun item -> proxyList.addEnd(item) |> ignore)
            proxyList
Run Code Online (Sandbox Code Playgroud)

用法:Ian Griffiths的ForMemberFs

this.CreateMap<SourceItemType list, Proxies.List>().ConvertUsing<ListTypeConverter<SourceItemType, DestItemType>>()

this.CreateMap<SourceType, DestType>().
    ForMemberFs((fun d -> d.MyNonGenericList), (fun opts -> opts.MapFrom(fun s -> s.MyGenericList))).
Run Code Online (Sandbox Code Playgroud)

如果我的主地图上只有一个属性从a映射,这样可以正常工作'a list -> Proxy.List.但是当我'b -> Proxy.List从那时引入第二个映射时,我得到一个InvalidCastException.

引入第二个映射会导致异常:

this.CreateMap<SourceItemType list, Proxies.List>().ConvertUsing<ListTypeConverter<SourceItemType, DestItemType>>()
this.CreateMap<SourceItemType2 list, Proxies.List>().ConvertUsing<ListTypeConverter<SourceItemType2, DestItemType2>>()

this.CreateMap<SourceType, DestType>().
    ForMemberFs((fun d -> d.MyNonGenericList), (fun opts -> opts.MapFrom(fun s -> s.MyGenericList))).
    ForMemberFs((fun d -> d.MyNonGenericList2), (fun opts -> opts.MapFrom(fun s -> s.MyGenericList2))).
Run Code Online (Sandbox Code Playgroud)

例外:

Unable to cast object of type 'obj' to type 'DestItemType'
Run Code Online (Sandbox Code Playgroud)

Aar*_*mer 1

所以,我的问题比 F# 和 AutoMapper 更深一些。Proxies.List 类型实际上是通过我们内部编写的 Microsoft Dynamics AX 的 TypeProvider 获取的。我想从方程中排除该变量,因此我使用System.Collections.Generic.List<'t> -> System.Collections.ArrayList(非通用)编写了一个简单的脚本,并且我能够成功地将背上的项目转换ArrayList为正确的“目标”类型。

当我在这里时,我们为 AutoMapper 想出了一些非常酷的 F# 助手:

type OptionExpressions =
    static member MapFrom<'source, 'destination, 'sourceMember, 'destinationMember> (e: 'source -> 'sourceMember) =
        System.Action<IMemberConfigurationExpression<'source, 'destination, 'destinationMember>> (fun (opts: IMemberConfigurationExpression<'source, 'destination, 'destinationMember>) -> opts.MapFrom(e))
    static member UseValue<'source, 'destination, 'value> (e: 'value) =
        System.Action<IMemberConfigurationExpression<'source, 'destination, 'value>> (fun (opts: IMemberConfigurationExpression<'source, 'destination, 'value>) -> opts.UseValue(e))
    static member Ignore<'source, 'destination, 'destinationMember> () =
        System.Action<IMemberConfigurationExpression<'source, 'destination, 'destinationMember>> (fun (opts: IMemberConfigurationExpression<'source, 'destination, 'destinationMember>) -> opts.Ignore())
Run Code Online (Sandbox Code Playgroud)

用法:

// Shortened local helpers
let mapFrom = OptionExpressions.MapFrom
let ignoreMap = OptionExpressions.Ignore
let useValue = OptionExpressions.UseValue

this.CreateMap<Source, Destination>()
    .ForMemberFs((fun d -> d.DestMember1),  mapFrom (fun s -> s.SourceMember1))
    .ForMemberFs((fun d -> d.DestMember2),  useValue (MyValue))
    .ForMemberFs((fun d -> d.DestMember3),  ignoreMap ())
Run Code Online (Sandbox Code Playgroud)