Automapper:水合int吗?根据条件 [英] Automapper: Hydrate int? based on conditions
问题描述
我有以下代码:
[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:
但是我不知道如何:
- 应用基于
int?
的逻辑,而无需一一定义. - 将
allowOverride
布尔值包含到映射器中.
- Apply the logic based on
int?
without defining it one by one. - 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屋!