我需要使用automapper将一个类转换为另一个类,我的对象如下所示:
public class Foo
{
public List<object> Objects { get; set; }
}
public class Bar
{
public List<object> Objects { get; set; }
}
public class FooItem
{
public string Name { get; set; }
}
public class BarItem
{
public string Name { get; set; }
}
项目可能有更多类型,不仅仅是FooItem
和BarItem
,但为了简单起见,我只是使用这两种类型,我需要进行此设计。
我尝试过类似转换器之类的东西,但仍然没有运气。
这里是当前的基本转换代码
Mapper.Initialize(cfg =>
{
cfg.CreateMap<FooItem, BarItem>();
cfg.CreateMap<Foo, Bar>();
});
var foo = new Foo()
{
Objects = new List<object>() { new FooItem() { Name = "name" } }
};
var map = Mapper.Map<Foo, Bar>(foo);
目标是Bar
对象在运行时包含BarItems
列表,但到目前为止,我只是在运行时设法得到FooItem
的列表。
有什么想法吗?
答案 0 :(得分:2)
您是否只对BarItems
列表感到满意?在这种情况下,您可以这样做:
var map = Mapper.Map<IEnumerable<FooItem>, List<BarItem>>(foo.Objects.Cast<FooItem>());
更新:您可以这样做。
class Program
{
static void Main(string[] args)
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<FooItem, BarItem>();
cfg.CreateMap<Foo, Bar>()
.ForMember(dest => dest.Objects, opt => opt.ResolveUsing<CustomResolver>());
});
Mapper.AssertConfigurationIsValid();
var foo = new Foo()
{
Objects = new List<object>() { new FooItem() { Name = "name" } }
};
//var map = Mapper.Map<IEnumerable<FooItem>, List<BarItem>>(foo.Objects.Cast<FooItem>());
var map = Mapper.Map<Foo, Bar>(foo);
}
}
public class CustomResolver : IValueResolver<Foo, Bar, List<object>>
{
public List<object> Resolve(Foo source, Bar destination, List<object> member, ResolutionContext context)
{
var map = Mapper.Map<IEnumerable<FooItem>, List<BarItem>>(source.Objects.Cast<FooItem>());
return map.Cast<object>().ToList();
}
}
答案 1 :(得分:2)
您可以在ConstructUsing
子句中进行类型检查:
cfg.CreateMap<object, object>()
.ConstructUsing(src => {
if (src is FooItem) {
return Mapper.Map<BarItem>(src);
}
// ...
throw new InvalidOperationException($"Can not map source item of type '{src.GetType().FullName}'.");
});
但您可能需要为Objects
集合中的项目引入界面,因为地图对象 - &gt; object会覆盖所有其他地图,但我们想要使用地图FooItem - &gt; BarItem。
答案 2 :(得分:0)
受到@Ogglas的启发,我设法找到了一个有趣的解决方案,无需检查所有类型。
基本上我写了自己的ITypeConverter
public class CustomResolver : ITypeConverter<List<object>, List<object>>
{
public List<object> Convert(List<object> source, List<object> destination, ResolutionContext context)
{
var objects = new List<object>();
foreach (var obj in source)
{
var destinationType = context.ConfigurationProvider.GetAllTypeMaps().First(x => x.SourceType == obj.GetType()).DestinationType;
var target = context.Mapper.Map(obj, obj.GetType(), destinationType);
objects.Add(target);
}
return objects;
}
}
从上下文中获取每种类型的正确映射。目前还不知道空值等等......
然后,配置automapper
Mapper.Initialize(cfg =>
{
cfg.CreateMap<FooItem, BarItem>();
cfg.CreateMap<List<object>, List<object>>().ConvertUsing<CustomResolver>();
cfg.CreateMap<Foo, Bar>();
});