2016-10-12 52 views
6

我創建了一個ListTypeConverter:如何使用AutoMapper將具有多個通用列表的對象映射到具有相應非通用列表的另一個對象?

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 

與用法:ForMemberFs by Ian Griffiths

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))). 

這工作得很好,如果我只對我說從'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))). 

例外:

Unable to cast object of type 'obj' to type 'DestItemType' 

回答

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()) 

用法:

// 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()) 
相關問題