【问题标题】:Mapping an object to self将对象映射到自身
【发布时间】:2022-09-23 05:24:49
【问题描述】:

我们目前在代码中使用 AutoMapper v8,并计划升级到 9.0+。为此,我们需要将所有静态映射器转换为基于实例的映射器。

我们的代码库中有很多代码,如下所示。

public class ConfigModel 
{
    public int MyProperty1 { get; set; }
    ...
    
    public ConfigModel Load(ConfigEntity config)
    {
        Mapper.Map(config, this);
        return this;
    }
}

我正在寻找可以用IMapper 做的类似事情。我们只需要将实体映射到模型中的属性。

  • 欢迎来到堆栈溢出。请通过tour 了解 Stack Overflow 的工作原理,并阅读How to Ask 了解如何提高问题的质量。目前尚不清楚您在问什么或问题是什么。请edit你的问题包括你想问的问题。如果可能,请添加minimal reproducible example

标签: c# automapper


【解决方案1】:

我假设您正在使用依赖注入。您需要在某个地方注入映射器实例。我推荐一个工厂。

interface IConfigModelFactory
{
    ConfigModel CreateInstance(ConfigEntity config);
}

class ConfigModelFactory : IConfigModelFactory
{
    protected readonly IMapper _mapper;

    public ConfigModelFactory(IMapper mapper)
    {
        _mapper = mapper;
    }

    public ConfigModel CreateInstance(ConfigEntity entity)
    {
        return new ConfigModel(_mapper, entity);
    }
}

public class ConfigModel
{
    public ConfigModel(IMapper mapper, ConfigEntity entity)
    {
        mapper.Map(entity, this);
    }
}

现在,无论您需要创建ConfigModel 类的实例,注入您的工厂,映射器都会随之出现(假设您已经注册了它)。使用工厂而不是直接使用new

【讨论】:

    【解决方案2】:

    事实证明,AutoMapper 有一个具有这样定义的方法。我在文档页面中找不到它,但这是包的一部分。

    //
    // Summary:
    //     Execute a mapping from the source object to the existing destination object.
    //
    // Parameters:
    //   source:
    //     Source object to map from
    //
    //   destination:
    //     Destination object to map into
    //
    // Type parameters:
    //   TSource:
    //     Source type to use
    //
    //   TDestination:
    //     Destination type
    //
    // Returns:
    //     The mapped destination object, same instance as the destination object
    TDestination Map<TSource, TDestination>(TSource source, TDestination destination);
    

    所以我们可以做到这一点,并且在模型中,我们可以将实体映射到自身。

    this.mapper.Map(entity, this);
    

    这可以像这样使用 Moq 进行单元测试。

    var mapper = autoMocker.GetMock<IMapper>();
    mapper.Setup(a => a.Map<Entity, Model>(It.IsAny<Entity>()))
        .Returns(new Model
        {
            Prop1 = "val 1",
            Prop2 = "val 2",
            ...
        });
    

    【讨论】:

      【解决方案3】:

      我猜你有一个 ConfigModel 类,里面是这个 Load 方法,像这样:

      public class ConfigModel{
         int MyProperty1 { get; private set; }
      
         public ConfigModel Load(ConfigEntity config)
         {
            Mapper.Map(config, this);
            return this;
         }
      
         public ConfigModel(int myProperty1) // <-constructor
         {
            MyProperty1 = myProperty1;
         }
      }
      

      因此,要将对象映射到自身,您甚至不需要映射器,有一个将传入对象映射到该对象的方法:

      public class ConfigModel{
         int MyProperty1 { get; private set; }
      
         public ConfigModel Load(ConfigEntity config)
         {
            Map(config);
            return this;
         }
      
         public void Map(ConfigModel configModel) // <- mapping method without using AutoMapper, using something like that does not collide with other mappings using AutoMapper
         {
            this.MyProperty1 = configModel.MyProperty1
            //... you can map as many properties as you like
         }
      
         public ConfigModel(int myProperty1) // <-constructor
         {
            MyProperty1 = myProperty1;
         }
      }
      

      【讨论】:

      • 我从您对我的问题的回答中复制了类定义,因为我认为这会使问题更具可读性。很抱歉未经允许就这样做了。
      • 可以的,没问题
      猜你喜欢
      • 2019-05-27
      • 1970-01-01
      • 2016-11-07
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 2012-04-23
      • 1970-01-01
      • 2018-10-31
      相关资源
      最近更新 更多