一个DTO你如何映射到使用AutoMapper嵌套对象现有的对象实例? [英] How do you map a Dto to an existing object instance with nested objects using AutoMapper?

查看:2923
本文介绍了一个DTO你如何映射到使用AutoMapper嵌套对象现有的对象实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的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

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,实体)来更新现有的实体,但是当我试图映射 Dto.SubProperty Entity.Sub.SubProperty 我得到一个例外的必须解析到顶级成员参数名称:lambdaEx pression 的。

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

如果我创建 DTO 映射到子实体使用 FromMember 然后 Entity.Sub 被替换子实体,但是这不是我想要的。我只是想它来更新子实体的现有实例对子属性属性实体

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℃的组合,解决了这个问题; T&GT;()办法和实施<$和c $ C> IValueResolver ConvertUsing&LT; T&GT;()办法和实施 ITypeConverter&LT; TSource,TDestination&GT;

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 被替换子实体这是没有好,当你想更新实体将被保存到数据库中的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.

如果您修改 MapperConfig2 来代替,你仍然有更新的字符串属性之前,但是 entity.sub 仍具有子实体,它有相同的实例之前。运行与 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 来preserve的值 entity.Sub

The key difference in MapperConfig2 is that ResolveUsing is used along with MyResolver to preserve the value of entity.Sub.

这篇关于一个DTO你如何映射到使用AutoMapper嵌套对象现有的对象实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆