我创建了一个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)
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)
所以,我的问题比 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)