Automapper:水合int吗?根据条件 [英] Automapper: Hydrate int? based on conditions

查看:131
本文介绍了Automapper:水合int吗?根据条件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

[Test]
public void ConditionalMapping()
{
    var src = new Sample1 {Age = 1, Number = null};
    var dest = new Sample2 {Age = null, Number = 1};

    Hydrate(src, dest, false);

    Assert.That(dest.Age, Is.EqualTo(1));
    Assert.That(dest.Number, Is.EqualTo(1));

    src = new Sample1 {Age = null, Number = 1};
    dest = new Sample2 {Age = 1, Number = null};

    Hydrate(src, dest, true);

    Assert.That(dest.Age, Is.Null);
    Assert.That(dest.Number, Is.EqualTo(1));
}

public void Hydrate(Sample1 src, Sample2 dest, bool allowOverride)
{
    if (!dest.Age.HasValue || allowOverride)
        dest.Age = src.Age;

    if (!dest.Number.HasValue || allowOverride)
        dest.Number = src.Number;
}

public class Sample1
{
    public int? Age { get; set; }
    public int? Number { get; set; }
}

public class Sample2
{
    public int? Age { get; set; }
    public int? Number { get; set; }
}

如果值为null,除非allowOverride = true,它基本上会水化int?,它将在不检查字段值的情况下对值进行水化.

Which basically hydrates an int? if the value is null unless allowOverride = true, in which it will hydrate the value without checking the value of the field.

我将如何在Automapper中执行此操作?

How would I go about doing this in Automapper?

我知道您可以使用.Condition(),如下所示:

I know that you can use .Condition() as shown here:

自动映射器的条件被忽略

但是我不知道如何:

  1. 应用基于int?的逻辑,而无需一一定义.
  2. allowOverride布尔值包含到映射器中.
  1. Apply the logic based on int? without defining it one by one.
  2. Include the allowOverride boolean to the Mapper.

推荐答案

我可能已经为您找到了一个潜在的解决方案-取决于您希望allowOverride标志如何工作.

I may have found a potential solution for you - depending on how you want the allowOverride flag to work.

如果您希望该标志对所有映射操作相同,则可以如下创建TypeConverter

If you want the flag to operate the same for all mappings you can create a TypeConverter as follows

public class NullableIntConverter : ITypeConverter<int?, int?>
{
    private bool AllowOverrides { get; set;}

    public NullableIntConverter(bool allowOverrides)
    {
        AllowOverrides = allowOverrides;
    }

    public int? Convert(ResolutionContext context)
    {
        var source = context.SourceValue as int?;
        var destination = context.DestinationValue as int?;
        if (destination.HasValue && !AllowOverrides)
            return destination;
        else
            return source;
    }
}

像这样初始化它:

Mapper.CreateMap<Sample1, Sample2>();
Mapper.CreateMap<int?, int?>().ConvertUsing(new NullableIntConverter(true));
Mapper.AssertConfigurationIsValid();

现在它将检查目标的值,并根据您的构造函数参数适当地覆盖它.

It will now check the destination for a value, and override it as appropriate depending on your constructor argument.

OR

如果您希望能够为每个映射专门配置它,则可以使用ValueResolver(请注意,此代码可以进行一些额外的验证):

If you want to be able to configure it for each mapping specifically, then you could use a ValueResolver (note that this code could do with some extra validation):

public class NullableIntResolver : IValueResolver
{
    public bool AllowOverrides { get; set; }

    public NullableIntResolver(bool allowOverrides)
    {
        AllowOverrides = allowOverrides;
    }

    public ResolutionResult Resolve(ResolutionResult source)
    {
        // Add validation for source and destination types
        return source.New(
                   ResolveCore((int?) source.Value,
                               DestinationMemberValue(source.Context)),
                   typeof(int?));
    }

    public int? ResolveCore(int? source, int? destination)
    {
        if (destination.HasValue && !AllowOverrides)
            return destination;
        else
            return source;
    }

    private int? DestinationMemberValue(ResolutionContext context)
    {
        var destObject = context.DestinationValue;
        var destMemberName = context.MemberName;
        return (int?) destObject
                          .GetType()
                          .GetProperty(destMemberName)
                          .GetValue(destObject, null);
    }
}

然后您可以像这样初始化映射:

You can then initialise your mappings like this:

var allowOverrides = true;
Mapper.CreateMap<Sample1, Sample2>()
    .ForMember(dest => dest.Age,
               opt => opt.ResolveUsing<NullableIntResolver>()
               .FromMember(src => src.Age)
               .ConstructedBy(() => new NullableIntResolver(allowOverrides)))
    .ForMember(dest => dest.Number,
               opt => opt.ResolveUsing<NullableIntResolver>()
               .FromMember(src => src.Number)
               .ConstructedBy(() => new NullableIntResolver(allowOverrides)));
Mapper.AssertConfigurationIsValid();

这篇关于Automapper:水合int吗?根据条件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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