如果TSource为Nullable <datetime>

时间:2018-10-10 23:06:25

标签: c# datetime lambda automapper nullable

我有一个如此定义的AutoMapper映射

CreateMap<DateTime?, DateString>()
    .ForMember(dest => dest.Value, opt => opt.ResolveUsing(src => src.HasValue ? src.Value.ToString("yyyyMMdd") : String.Empty));

DateString被定义为

public class DateString
{
    public String Value { get; set; }
}

Value属性是一个String,它以yyyymmdd格式表示日期,因此为了适应这种预期格式,我将表示为DateTime类型的日期转换为String格式。

上面的地图是从另一个这样定义的地图触发的

CreateMap<DateTimeDetails, PickupDetails>()
    .ForMember(dest => dest.time, opt => opt.MapFrom(src => src));

DateTimeDetailsPickupDetails类定义为

public class DateTimeDetails
{
    public Nullable<DateTime> Date { get; set; }
    public String Time { get; set; }
    public Int32 TimeZoneOffset { get; set; }
}

public class PickupDetails
{
    public TimeString time { get; set; }
    public DateString date { get; set; }
}

因此一般流程如下:

DateTimeDetails转换为PickupDetails时,属性PickupDetails.dateDateTimeDetails.Date自动匹配,而无需使用.ForMember().MapFrom(),并且触发DateTime? -> DateString地图。

根据DateString.Value源对象是否具有值,将yyyymmdd属性设置为String.EmptyNullable<DateTime>

我遇到的问题是,如果我将TSource的{​​{1}}映射为DateTime? -> DateStringNullable<DateTime>为空,则AutoMapper无法识别{{ 1}}签名并映射DateTime?属性。它将引发错误

<TSource, TDestination>

如果我将地图做得更明确

PickupDetails.date

尝试进入解析器的逻辑,我不会碰到解析器中任何地方的任何断点。

要使其正常工作,唯一的方法是将Error mapping types. Mapping types: DateTimeDetails -> PickupDetails Type Map configuration: DateTimeDetails -> PickupDetails Property: date 更改为不可空的CreateMap<DateTime?, DateString>() .ForMember(dest => dest.Value, opt => opt.ResolveUsing(src => { if (src.HasValue) { return src.Value.ToString("yyyyMMdd"); } else { return String.Empty; } })); 类型,并实施TSource检查而不是DateTime检查在这样的三元声明中获得回报

!= null

AutoMapper将以这种格式识别Nullable<DateTime>.HasValue签名,并自动从CreateMap<DateTime, DateString>() .ForMember(dest => dest.Value, opt => opt.ResolveUsing(src => src != null ? src.ToString("yyyyMMdd") : String.Empty)); 映射中映射<TSource, TDestination>

我看不到我要去哪里,为什么我的PickupDetails.date地图的DateTimeDetails -> PickupDetails不能是TSourceDateTime? -> DateString且必须是不能为空的Nullable<DateTime>

Here是该问题的存储库。该在线编译器无法运行AutoMapper V7.0.1,因此正在使用V6.2.2,并且6.2.2的行为仍然不正确,但与我在上面解释的7.0.1中所遇到的不一样在这篇文章中。

**编辑1:**

在Lucian Bargaoanu的帮助下,我想出了更多有关此映射正在发生的事情。以下是具有相同DateTime?语句的同一映射的执行计划,唯一更改的是DateTime

AutoMapper Execution Plans

对于使用.ForMember() TSource的地图,将执行if-else块来检查Nullable<DateTime>属性。如果为null,则它不返回TSource类的$src实例,而仅返回指向它的指针,导致new属性未设置为等于其类类型的空实例,这将让它包含TDestination属性,以获取destObj.date的完整访问路径,.Value只是设置为null。

我不确定的是这是否是插入此destObj.date.Value的.Net Core框架行为,请检查lambda是否正在使用destObj.date变量,或者AutoMapper是否正在添加它。正如您在下面的右图所示的执行计划中所见的那样,我正在尝试自己处理if($src == null)场景。但是到目前为止,我永远都不会到达那里。

我也不确定Nullable<T>变量在整个AutoMapper中的作用,但是现在我的$src == null映射出现$typeMapDestination错误。

我在想这可能是因为Error mapping types.块阻止了CreateMap<Nullable<DateTime>, DateString>()变量被操纵/返回,因此if($src == null)中指定的目标属性实际上从未被“映射”过因此会引发错误。

还有一个值得注意的行为是不可空的$typeMapDestination映射,即使发送了空值,尽管下面的代码块也是如此

.ForMemeber()

某种原因导致尝试失败并跌至下面的两个catch块之一。 if / else块的DateTime -> DateString部分将不会触发。并且$resolvedValue = .Try { .If($src != null) { .Call $src.ToString("yyyyMMdd") } .Else { System.String.Empty } } .Catch(System.NullReferenceException) { .Default(System.String) } .Catch(System.ArgumentNullException) { .Default(System.String) }; 等于null,而不是else { System.String.Empty }属性为destObj.date的{​​{1}}新实例。

0 个答案:

没有答案