具有“Value”和“HasValue”的结构类型的通用自动映射器前提条件
Generic Automapper Precondition for Struct type with `Value`and `HasValue`
我正在使用 Automapper 和 Hot Chocolate。我在名为 Optional<>
的源 class 属性上使用结构类型,它具有方法 .Value
和 .HasValue
,用于确定客户端是否传入了这些值或不是。这用于从客户端到数据库的部分 update/patching。例如:
我的model/dto:
public Optional<string> Name { get; init; }
在我的自动映射器配置文件中,我可以这样做:
.ForMember(dest => dest.Name, opt => {
opt.PreCondition(src => src.Name.HasValue))
opt.MapFrom(src => src.Name.Value)
})
这有效并且具有我想要的行为。但是,我不想最终为我的所有属性编写手动映射代码,这就是我首先使用 Automapper 的原因。
因此,我试图使此行为对类型 IOptional
的所有源类型属性通用。
我尝试了很多不同的东西。扩展方法和反射,以及使用类型转换器。
Automapper 自定义类型转换器将无法工作,因为您必须 return 一个值并且不能“退出”映射。
我已经尝试为 PreCondition
创建扩展方法,但我只能访问 AutoMapper 的 ResolverContext
对象,而且我还没有弄清楚如何利用它。例如:
.ForAllOtherMembers(o => o.PreCondition((src, dest, rc) =>
// what do
));
有没有人做过类似的事情?我想它与 Nullable<>
结构的概念相同,但我找不到任何适用于这种情况的实现。
认为我找到了令我满意的解决方案:
捕获所有可选源类型并应用解析器。
ForAllPropertyMaps(pm =>
{
return pm.SourceType != null && pm.SourceMember != null && pm.SourceType.IsGenericType &&
(pm.SourceType.GetGenericTypeDefinition() == typeof(Optional<>));
}, (pm, c) =>
{
c.MapFrom<AutoMapperExtensions.Resolver, IOptional>(pm.SourceMember.Name);
});
基于 HasValue 解析:
public class Resolver : IMemberValueResolver<object, object, IOptional, object>
{
public object Resolve(object source, object destination, IOptional sourceMember, object destinationMember, ResolutionContext context)
{
return sourceMember.HasValue ? sourceMember.Value : destinationMember;
}
}
可以写得更漂亮,类型检查可能会有所不同,但这是一个起点。基于此评论:https://github.com/AutoMapper/AutoMapper/issues/2999#issuecomment-472692335
我正在使用 Automapper 和 Hot Chocolate。我在名为 Optional<>
的源 class 属性上使用结构类型,它具有方法 .Value
和 .HasValue
,用于确定客户端是否传入了这些值或不是。这用于从客户端到数据库的部分 update/patching。例如:
我的model/dto:
public Optional<string> Name { get; init; }
在我的自动映射器配置文件中,我可以这样做:
.ForMember(dest => dest.Name, opt => {
opt.PreCondition(src => src.Name.HasValue))
opt.MapFrom(src => src.Name.Value)
})
这有效并且具有我想要的行为。但是,我不想最终为我的所有属性编写手动映射代码,这就是我首先使用 Automapper 的原因。
因此,我试图使此行为对类型 IOptional
的所有源类型属性通用。
我尝试了很多不同的东西。扩展方法和反射,以及使用类型转换器。
Automapper 自定义类型转换器将无法工作,因为您必须 return 一个值并且不能“退出”映射。
我已经尝试为 PreCondition
创建扩展方法,但我只能访问 AutoMapper 的 ResolverContext
对象,而且我还没有弄清楚如何利用它。例如:
.ForAllOtherMembers(o => o.PreCondition((src, dest, rc) =>
// what do
));
有没有人做过类似的事情?我想它与 Nullable<>
结构的概念相同,但我找不到任何适用于这种情况的实现。
认为我找到了令我满意的解决方案:
捕获所有可选源类型并应用解析器。
ForAllPropertyMaps(pm =>
{
return pm.SourceType != null && pm.SourceMember != null && pm.SourceType.IsGenericType &&
(pm.SourceType.GetGenericTypeDefinition() == typeof(Optional<>));
}, (pm, c) =>
{
c.MapFrom<AutoMapperExtensions.Resolver, IOptional>(pm.SourceMember.Name);
});
基于 HasValue 解析:
public class Resolver : IMemberValueResolver<object, object, IOptional, object>
{
public object Resolve(object source, object destination, IOptional sourceMember, object destinationMember, ResolutionContext context)
{
return sourceMember.HasValue ? sourceMember.Value : destinationMember;
}
}
可以写得更漂亮,类型检查可能会有所不同,但这是一个起点。基于此评论:https://github.com/AutoMapper/AutoMapper/issues/2999#issuecomment-472692335