问题描述
我有以下 Dto 和带有嵌套子实体的实体.
I have the following Dto and entity with a nested sub entity.
public class Dto
{
public string Property { get; set; }
public string SubProperty { get; set; }
}
public class Entity
{
public string Property { get; set; }
public SubEntity Sub { get; set; }
}
public class SubEntity
{
public string SubProperty { get; set; }
}
我如何使用 AutoMapper 设置映射,以允许我使用 Dto 中的值更新 Entity 的现有实例.
How can I set up a mapping with AutoMapper that will allow me to update an existing instance of Entity with the values from a Dto.
我正在使用 Mapper.Map(dto, entity)
更新现有实体,但是当我尝试将 Dto.SubProperty
映射到 Entity.Sub.SubProperty
我得到一个异常必须解析为顶级成员.参数名称:lambdaExpression".
I'm using Mapper.Map(dto, entity)
to update an existing entity but when I try to map Dto.SubProperty
to Entity.Sub.SubProperty
I get an exception for "must resolve to top-level member. Parameter name: lambdaExpression".
如果我使用 FromMember
创建从 Dto
到 SubEntity
的映射,则 Entity.Sub
被替换为SubEntity
的新实例,但这不是我想要的.我只希望它更新 Entity
的 Sub
属性上的 SubEntity
现有实例的属性.
If I create a mapping from Dto
to SubEntity
using FromMember
then Entity.Sub
gets replaced with a new instance of SubEntity
but that's not what I want. I just want it to update the properties of the existing instance of SubEntity
on the Sub
property of Entity
.
我怎样才能做到这一点?
推荐答案
我通过使用 ResolveUsing
方法和实现 IValueResolver
的组合解决了它和 ConvertUsing
方法并实现 ITypeConverter
.
I solved it by using a combination of the ResolveUsing<T>()
method and implementing IValueResolver
and the ConvertUsing<T>()
method and implementing ITypeConverter<TSource,TDestination>
.
我的一些映射场景比正常情况更复杂,包括双向映射和嵌套类和嵌套集合.以上帮助我解决了这些问题.
Some of my mapping scenarios are more complicated than normal including bidirectional mapping and nested classes and nested collections. The above helped me to solve them.
根据要求,我提供了一个示例解决方案.这个例子比我处理的实际类型简单得多.
As requested, I've included an example solution. This example is much simpler than the actual types I was dealing with.
using System;
using AutoMapper;
namespace TestAutoMapperComplex
{
public class Dto
{
public string Property { get; set; }
public string SubProperty { get; set; }
}
public class Entity
{
public string Property { get; set; }
public SubEntity Sub { get; set; }
}
public class SubEntity
{
public string SubProperty { get; set; }
}
static class MapperConfig
{
public static void Initialize()
{
Mapper.CreateMap<Dto, Entity>()
.ForMember(entity => entity.Sub, memberOptions =>
memberOptions.MapFrom(dto => dto));
Mapper.CreateMap<Dto, SubEntity>();
}
}
static class MapperConfig2
{
private class MyResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
var destinationSubEntity = ((Entity)source.Context.DestinationValue).Sub;
Mapper.Map((Dto)source.Value, destinationSubEntity);
return source.New(destinationSubEntity, typeof(SubEntity));
}
}
public static void Initialize()
{
Mapper.CreateMap<Dto, Entity>()
.ForMember(entity => entity.Sub, memberOptions =>
memberOptions.ResolveUsing<MyResolver>());
Mapper.CreateMap<Dto, SubEntity>();
}
}
class Program
{
static void Main(string[] args)
{
MapperConfig.Initialize();
var dto = new Dto {Property = "Hello", SubProperty = "World"};
var subEntity = new SubEntity {SubProperty = "Universe"};
var entity = new Entity {Property = "Good bye", Sub = subEntity};
Mapper.Map(dto, entity);
Console.WriteLine(string.Format("entity.Property == {0}, entity.Sub.SubProperty == {1}",
entity.Property, entity.Sub.SubProperty));
Console.WriteLine(string.Format("entity.Sub == subEntity: {0}",
entity.Sub == subEntity));
}
}
}
如果您运行使用 MapperConfig
的示例,您将获得以下输出:
If you run the example, which is using MapperConfig
, you'll get the following output:
entity.Property == Hello, entity.Sub.SubProperty == World
entity.Sub == subEntity: False
字符串属性都按照人们希望的方式更新,但是 entity.Sub
被替换为 SubEntity
的新实例想要更新将持久化到数据库的 ORM 的实体.
The string properties all get updated as one would want them to, but entity.Sub
gets replaced with a new instance of SubEntity
which is no good for when you are wanting to update entities for an ORM that will be persisted to a database.
如果您修改 Main
以便使用 MapperConfig2
,您仍然会像以前一样更新字符串属性,但是,entity.sub
仍然具有与之前相同的 SubEntity
实例.使用 MapperConfig2
运行示例给出以下输出:
If you modify Main
so that MapperConfig2
is used instead, you'll still have the string properties updated as before, but, entity.sub
still has the same instance of SubEntity
that it had before. Running the example with MapperConfig2
gives this output:
entity.Property == Hello, entity.Sub.SubProperty == World
entity.Sub == subEntity: True
MapperConfig2
的主要区别在于 ResolveUsing
与 MyResolver
一起使用以保留 entity.Sub的值代码>.
The key difference in MapperConfig2
is that ResolveUsing
is used along with MyResolver
to preserve the value of entity.Sub
.
这篇关于如何使用 AutoMapper 将 Dto 映射到具有嵌套对象的现有对象实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!