【问题标题】:Create two Automapper maps between the same two object types在相同的两种对象类型之间创建两个 Automapper 映射
【发布时间】:2012-12-25 07:45:59
【问题描述】:

我在 WCF 服务中使用 AutoMapper 来返回 User 对象。 User 具有诸如 AccountTeams 之类的属性,而 AccountTeams 本身具有子对象。所有类都有 AutoMapper 地图。

根据调用的 WCF OperationContract,我想返回不同数量的数据。我希望一个 OperationContract 返回 User 对象而不填充其 AccountTeams 属性(及其子级),另一个 OperationContract 返回 User 并填写整个属性链。

有没有办法在相同的两个对象之间有两个不同的映射,还是我需要执行完整映射并null 去掉我不想从服务返回的属性?

【问题讨论】:

  • 您是否考虑过返回两个不同的UserDTO 对象?
  • 为了清楚起见,您正在从 User 映射到 ??

标签: c# .net wcf automapper


【解决方案1】:

Kevin Kalitowski 对 wal 的回答提出了一个很好的观点:如果我们需要两种配置来处理需要不同的映射,那么我们是否不必复制所有其他常见的映射?

我想我已经找到了一种使用配置文件的方法:为每个唯一映射创建一个配置文件,为公共映射创建第三个配置文件。然后创建两个配置,一个用于每个唯一配置文件,但也将通用配置文件添加到每个配置。

例如,在 AutoMapper 4.2 中:

要映射的类:用户和车辆:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class Vehicle
{
    public int FleetNumber { get; set; }
    public string Registration { get; set; }
}

简介:

public class Profile1 : Profile
{
    protected override void Configure()
    {
        base.CreateMap<User, User>();
    }
}

public class Profile2 : Profile
{
    protected override void Configure()
    {
        base.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
    }
}

public class CommonProfile : Profile
{
    protected override void Configure()
    {
        base.CreateMap<Vehicle, Vehicle>();
    }
}

然后创建配置并映射对象:

[TestMethod]
public void TestMethod()
{
    var user = new User() { Name = "John", Age = 42 };
    var vehicle = new Vehicle {FleetNumber = 36, Registration = "XYZ123"};

    var configuration1 = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile<CommonProfile>();
        cfg.AddProfile<Profile1>();
    });

    var mapper1 = configuration1.CreateMapper();
    var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age
    var mappedVehicle1 = mapper1.Map<Vehicle, Vehicle>(vehicle);//Maps both FleetNumber 
                                                                //and Registration.

    var configuration2 = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile<CommonProfile>();
        cfg.AddProfile<Profile2>();
    });

    var mapper2 = configuration2.CreateMapper();
    var mappedUser2 = mapper2.Map<User, User>(user);//maps only Name
    var mappedVehicle2 = mapper2.Map<Vehicle, Vehicle>(vehicle);//Same as mappedVehicle1.
}

我试过了,效果很好。

【讨论】:

  • 这么简单的答案让我很生气,我没想到。我正在将接受的答案更改为这个答案,因为它更适合这个问题。
  • 使用依赖注入的时候呢。那里有办法选择吗?
  • @BradenBrown:我突然想到了三种可能性:(1) 你可以注入两个配置文件——一个普通的和一个独特的。然后在您的类中,您可以从传入的配置文件创建配置。然后从配置创建映射器; (2) 或者,您可以注入配置并从中创建映射器; (3) 第三种选择是注入映射器。
【解决方案2】:

我假设您正在从 User 映射到 User(如果不是,则只需更改目标类型)

在下面的例子中假设这个类:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

然后您可以使用单独的AutoMapper.Configuration 来定义 2 个地图:

[TestMethod]
public void TestMethod()
{
    var configuration1 = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
    var mapper1 = new MappingEngine(configuration1);
    configuration1.CreateMap<User, User>();

    var user = new User() { Name = "John", Age = 42 };
    var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age

    var configuration2 = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
    configuration2.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
    var mapper2 = new MappingEngine(configuration2);

    var mappedUser2 = mapper2.Map<User, User>(user);
    Assert.AreEqual(0, mappedUser2.Age);//maps only Name
}

为避免将所有其他类型映射两次,您可以添加一个通用方法,该方法采用Configuration,该方法映射可以从User 访问的所有内容,并在调用@ 之后在configuration1configuration2 上调用它987654330@.

更新

对于 Automapper 4.x,请使用以下内容:

var configuration1 = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<User, User>();
});

var mapper1 = configuration1.CreateMapper();
var user = new User() { Name = "John", Age = 42 };
var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age

var configuration2 = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
});

var mapper2 = configuration2.CreateMapper();
var mappedUser2 = mapper2.Map<User, User>(user);   //maps only Name

【讨论】:

  • 我认为这意味着如果可以从用户那里访问,我将不得不将每个其他类型映射两次。我希望有一种方法可以仅覆盖一个对象(用户)的地图。听起来这是不可能的。
  • 我不确定您是否可以这样做但是您可以添加一个通用方法,该方法采用 Configuration 映射可以从 User 和在调用CreateMap 之后,在configuration1configuration2 上调用它
  • Automapper 4.x 应该如何实现?
【解决方案3】:

我认为您可以使用here 中描述的不同配置对象来解决此问题,您可以找到此here 的示例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2013-01-19
    • 2013-01-10
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多