Collections 使用AutoMapper转换为只读集合

Collections 使用AutoMapper转换为只读集合,collections,f#,automapper,Collections,F#,Automapper,我需要找到一种方法将任意值列表转换为另一个列表 如果目标类型为ICollection,则AutoMapper可以工作,因为它正在创建一个实例并用Add填充它,但我的类型是不可变列表'a list 因此,如果我创建整数列表: let int=[1;2;3] 并尝试用 mapper.Map(ints) 它可以工作,但是如果我尝试用 mapper.Map 那么它就会失败 我找到了一个可以成功转换的解决方案,但它只能用于显式定义的类型 let cfg=MapperConfiguration( 乐趣

我需要找到一种方法将任意值列表转换为另一个列表

如果目标类型为
ICollection
,则AutoMapper可以工作,因为它正在创建一个实例并用
Add
填充它,但我的类型是不可变列表
'a list

因此,如果我创建整数列表:

let int=[1;2;3]
并尝试用

mapper.Map(ints)
它可以工作,但是如果我尝试用

mapper.Map
那么它就会失败

我找到了一个可以成功转换的解决方案,但它只能用于显式定义的类型

let cfg=MapperConfiguration(
乐趣c->
c、 CreateMap()|>忽略
c、 CreateMap()
.转炉(
乐趣来源(cfg:ResolutionContext)->
来源
|>Seq.map cfg.Mapper.map
|>序号(收费表)

所以问题是:如何编写类型转换器,将
'a列表
转换为
'b列表
,而无需明确定义这些类型的所有可能组合?

我终于找到了解决方案。我只需要看看这个映射器的源代码

解决方案并不完美,因为集合项转换并插入到
System.Collections.Generic.List
中,然后转换为
Microsoft.FSharp.Collections.FSharpList
,这会带来一些开销。但至少它起作用了

使用System.Collections.Generic;
使用System.Linq.Expressions;
使用静态System.Linq.Expressions.Expression;
使用AutoMapper.Mappers;
使用AutoMapper.Internal;
使用静态AutoMapper.Internal.CollectionMapperExpressionFactory;
使用Microsoft.FSharp.Collections;
公共类SeqToFSharpListMapper:EnumerableMapperBase
{
公共覆盖布尔IsMatch(类型对上下文)
=>context.SourceType.IsEnumerableType()
&&context.DestinationType.FullName.StartsWith(“Microsoft.FSharp.Collections.FSharpList`1”);
公共重写表达式MapExpression(IConfigurationProvider configurationProvider、ProfileMap ProfileMap、IMemberMap memberMap、,
表达式sourceExpression、表达式destExpression、表达式contextExpression)
{
var listType=typeof(List).MakeGenericType(ElementTypeHelper.GetElementType(destExpression.Type));
var list=MapCollectionExpression(configurationProvider、profileMap、memberMap、sourceExpression、Default(listType)、contextExpression、typeof(list)、MapItemExpr);
返回调用(typeof(ListModule).GetMethod(nameof(ListModule.OfSeq)).MakeGenericMethod(destExpression.Type.GenericTypeArguments[0]),list);
}
}
和F#

override.MapExpression(configurationProvider、profileMap、memberMap、sourceExpression、destExpression、contextExpression)=
让listType=typedefof.MakeGenericType(ElementTypeHelper.GetElementType destExpression.Type)
let list=MapCollectionExpression(configurationProvider、profileMap、memberMap、,
sourceExpression、Default(listType)、contextExpression、,
typedefof,
MapItem(funcpsdctxi->MapItemExpr(c,p,s,d,ctx,&i))//编译器需要显式lambda
向上广播调用(typedefof.Assembly//不想使用AssemblyQualifiedName
.GetType(“Microsoft.FSharp.Collections.ListModule”)//必须使用此技巧,因为我们无法通过typeof访问ListModule
.GetMethod(“of Seq”)
.MakeGenericMethod(destExpression.Type.GenericTypeArguments。[0]),
(列表)

我终于找到了解决办法。我只需要看看这个映射器的源代码

解决方案并不完美,因为集合项转换并插入到
System.Collections.Generic.List
中,然后转换为
Microsoft.FSharp.Collections.FSharpList
,这会带来一些开销。但至少它起作用了

使用System.Collections.Generic;
使用System.Linq.Expressions;
使用静态System.Linq.Expressions.Expression;
使用AutoMapper.Mappers;
使用AutoMapper.Internal;
使用静态AutoMapper.Internal.CollectionMapperExpressionFactory;
使用Microsoft.FSharp.Collections;
公共类SeqToFSharpListMapper:EnumerableMapperBase
{
公共覆盖布尔IsMatch(类型对上下文)
=>context.SourceType.IsEnumerableType()
&&context.DestinationType.FullName.StartsWith(“Microsoft.FSharp.Collections.FSharpList`1”);
公共重写表达式MapExpression(IConfigurationProvider configurationProvider、ProfileMap ProfileMap、IMemberMap memberMap、,
表达式sourceExpression、表达式destExpression、表达式contextExpression)
{
var listType=typeof(List).MakeGenericType(ElementTypeHelper.GetElementType(destExpression.Type));
var list=MapCollectionExpression(configurationProvider、profileMap、memberMap、sourceExpression、Default(listType)、contextExpression、typeof(list)、MapItemExpr);
返回调用(typeof(ListModule).GetMethod(nameof(ListModule.OfSeq)).MakeGenericMethod(destExpression.Type.GenericTypeArguments[0]),list);
}
}
和F#

override.MapExpression(configurationProvider、profileMap、memberMap、sourceExpression、destExpression、contextExpression)=
让listType=typedefof.MakeGenericType(ElementTypeHelper.GetElementType destExpression.Type)
let list=MapCollectionExpression(configurationProvider、profileMap、memberMap、,