英文:
Automapper with immutablelist
问题
在Source类中,我有一个IEnumerable<T>
属性。在目标类中,构造函数接受IEnumerable<T>
并将其转换为IImmutableList<T>
,然后赋值给一个IEnumerable<T>
属性。
以下是来自.Net 7.0中program.cs的代码副本:
// 复制并粘贴到.Net 7的Program.cs中应该可以工作。
using AutoMapper;
using System.Collections.Immutable;
var mapperConfiguration = new MapperConfiguration(cfg => {
cfg.CreateMap<ClassSource, ClassDestination>()
.ConstructUsing(m => new ClassDestination(m.Nums));
});
var mapper = mapperConfiguration.CreateMapper();
var classSource = new ClassSource();
var classDestination = mapper.Map<ClassDestination>(classSource);
Console.WriteLine(classDestination.Nums.Count());
public class ClassSource
{
public IEnumerable<int> Nums { get; init; } = new List<int> { 1, 2, 3, 4, 5 };
}
public class ClassDestination
{
public IEnumerable<int> Nums {get;}
public ClassDestination(IEnumerable<int> ints)
{
//Nums = ints.ToList(); // 这个可以工作
Nums = ints.ToImmutableList(); // 这个会引发异常
}
}
映射失败,报错为:AutoMapper.AutoMapperMappingException: '错误映射类型。'
如何解决这个问题?
英文:
In Source class, I have IEnumurable<T> Property. In the dest class, constructor takes the IEnumurable<T> and converts to IImmutableList<T> and assigns to a IEnumurable<T> property.
Here is the code copied from program.cs in .Net 7.0:
// Copy and Paste to Program.cs in .Net 7 should work.
using AutoMapper;
using System.Collections.Immutable;
var mapperConfiguration = new MapperConfiguration(cfg => {
cfg.CreateMap<ClassSource, ClassDestination>()
.ConstructUsing(m => new ClassDestination(m.Nums));
});
var mapper = mapperConfiguration.CreateMapper();
var classSource = new ClassSource();
var classDestination = mapper.Map<ClassDestination>(classSource);
Console.WriteLine(classDestination.Nums.Count());
public class ClassSource
{
public IEnumerable<int> Nums { get; init; } = new List<int> { 1, 2, 3, 4, 5 };
}
public class ClassDestination
{
public IEnumerable<int> Nums {get;}
public ClassDestination(IEnumerable<int> ints)
{
//Nums = ints.ToList(); // This works
Nums = ints.ToImmutableList(); // This throws exception
}
}
Mapping fails with: AutoMapper.AutoMapperMappingException: 'Error mapping types.'
How can this be solved?
答案1
得分: 2
如果您让代码运行,将会出现完整的错误消息:
未处理的异常。AutoMapper.AutoMapperMappingException:映射类型错误。
映射类型:
ClassSource -> ClassDestination
ClassSource -> ClassDestination
类型映射配置:
ClassSource -> ClassDestination
ClassSource -> ClassDestination
目标成员:
Nums
---> System.NotSupportedException:不支持指定的方法。
在 System.Collections.Immutable.ImmutableList`1.System.Collections.Generic.ICollection<T>.Clear()
在 lambda_method1(Closure, Object, ClassDestination, ResolutionContext)
--- 内部异常堆栈跟踪的末尾 ---
在 lambda_method1(Closure, Object, ClassDestination, ResolutionContext)
在 Program.<Main>$(String[] args)
命令由信号6终止
正如您所看到的,它试图调用目标属性 Nums
中不可变列表的 .Clear()
方法,从而引发了 NotSupportedException
异常。
因为您已经通过构造函数初始化了列表,如果需要使用 ConstructUsing()
,您应该明确忽略这个成员,通过在映射配置文件中添加相应的 .Ignore()
调用:
var mapperConfiguration = new MapperConfiguration(cfg =>#
{
cfg.CreateMap<ClassSource, ClassDestination>()
.ForMember(m => m.Nums, conf => conf.Ignore())
.ConstructUsing(m => new ClassDestination(m.Nums));
});
如果在调用构造函数之后,您的目标类已经完全初始化,您应该改为使用 .ConvertUsing()
:
var mapperConfiguration = new MapperConfiguration(cfg =>#
{
cfg.CreateMap<ClassSource, ClassDestination>()
.ConvertUsing(m => new ClassDestination(m.Nums));
});
英文:
If you let the code run, the full error message is:
Unhandled exception. AutoMapper.AutoMapperMappingException: Error mapping types.
Mapping types:
ClassSource -> ClassDestination
ClassSource -> ClassDestination
Type Map configuration:
ClassSource -> ClassDestination
ClassSource -> ClassDestination
Destination Member:
Nums
---> System.NotSupportedException: Specified method is not supported.
at System.Collections.Immutable.ImmutableList`1.System.Collections.Generic.ICollection<T>.Clear()
at lambda_method1(Closure, Object, ClassDestination, ResolutionContext)
--- End of inner exception stack trace ---
at lambda_method1(Closure, Object, ClassDestination, ResolutionContext)
at Program.<Main>$(String[] args)
Command terminated by signal 6
As you can see, it tries to call the method .Clear()
of the immutable list in the target property Nums
, which throws the NotSupportedException
.
Because you already initialize the list through the constructor, you should explicitly ignore this member by adding the corresponding .Ignore()
call to your mapping profile if you need to use ConstructUsing()
:
var mapperConfiguration = new MapperConfiguration(cfg =>#
{
cfg.CreateMap<ClassSource, ClassDestination>()
.ForMember(m => m.Nums, conf => conf.Ignore())
.ConstructUsing(m => new ClassDestination(m.Nums));
});
If your target class is already fully initialized after calling the constructor, you should instead use .ConvertUsing()
:
var mapperConfiguration = new MapperConfiguration(cfg =>#
{
cfg.CreateMap<ClassSource, ClassDestination>()
.ConvertUsing(m => new ClassDestination(m.Nums));
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论