C# 如何使用automapper映射子对象并使用
我使用automapper从模型映射到dto。在我的模型中,我想使用一个字符串,而在我的数据中,我想使用一个枚举。虽然它是嵌套的子对象,但我使用的是ForPath而不是FormMember。转换为字符串很容易,但是要将字符串转换回类型,我编写了一个ValueConverter。将ValueConverter与FormMember结合使用效果非常好,但是现在我需要将其与ForPath结合使用,这是不可能的。当我在automapper文档或堆栈中找不到它时,是否有其他解决方案来解决这个问题 这是我的MappingProfile 本部分与以下成员一起工作:C# 如何使用automapper映射子对象并使用,c#,asp.net-core,automapper,C#,Asp.net Core,Automapper,我使用automapper从模型映射到dto。在我的模型中,我想使用一个字符串,而在我的数据中,我想使用一个枚举。虽然它是嵌套的子对象,但我使用的是ForPath而不是FormMember。转换为字符串很容易,但是要将字符串转换回类型,我编写了一个ValueConverter。将ValueConverter与FormMember结合使用效果非常好,但是现在我需要将其与ForPath结合使用,这是不可能的。当我在automapper文档或堆栈中找不到它时,是否有其他解决方案来解决这个问题 这是我的
CreateMap<Dto, Model>()
.ForMember(dest => dest.Type, opt => opt.MapFrom(src => src.Type.ToString()))
.ReverseMap()
.ForMember(dest => dest.Type, opt => opt.ConvertUsing(new StringToEnumConverter<Type>(), src => src.Type));
CreateMap()
.FormMember(dest=>dest.Type,opt=>opt.MapFrom(src=>src.Type.ToString())
.ReverseMap()
.ForMember(dest=>dest.Type,opt=>opt.ConvertUsing(new-StringToEnumConverter(),src=>src.Type));
这部分我需要为路径和转换使用,这段代码是不允许的
CreateMap<Dto, Model>()
.ForPath(dest => dest.Type, opt => opt.MapFrom(src => src.Parent.Type.ToString()))
.ReverseMap()
.ForPath(dest => dest.Parent.Type, opt => opt.ConvertUsing(new StringToEnumConverter<Type>(), src => src.Type));
CreateMap()
.ForPath(dest=>dest.Type,opt=>opt.MapFrom(src=>src.Parent.Type.ToString())
.ReverseMap()
.ForPath(dest=>dest.Parent.Type,opt=>opt.ConvertUsing(new StringToEnumConverter(),src=>src.Type));
这是我的ValueConverter:
public class StringToEnumConverter<T> : IValueConverter<string, T> where T : struct
{
public T Convert(string source, ResolutionContext context)
{
if (!string.IsNullOrEmpty(source))
{
if (Enum.TryParse(source, out T result))
{
return result;
}
}
return default;
}
}
公共类StringToEnumConverter:IValueConverter其中T:struct
{
公共T转换(字符串源、ResolutionContext上下文)
{
如果(!string.IsNullOrEmpty(源))
{
if(枚举TryParse(源,输出结果))
{
返回结果;
}
}
返回默认值;
}
}
多亏了Lucian Bargaoanu,我才想出了这个解决方案。我将valueConverter重写为一个静态类,并使用MapFrom进行转换
public static class StringEnumExtension
{
public static TaskType ToTaskType(this string source)
{
return ToEnum<TaskType>(source);
}
public static TaskQuestionType ToTaskQuestionType(this string source)
{
return ToEnum<TaskQuestionType>(source);
}
private static T ToEnum<T>(string source) where T : struct
{
if (!string.IsNullOrEmpty(source))
{
if (Enum.TryParse(source, out T result))
{
return result;
}
}
return default;
}
}
公共静态类StringEnumExtension
{
公共静态任务类型ToTaskType(此字符串源)
{
返回ToEnum(源);
}
公共静态TaskQuestionType ToTaskQuestionType(此字符串源)
{
返回ToEnum(源);
}
私有静态T ToEnum(字符串源),其中T:struct
{
如果(!string.IsNullOrEmpty(源))
{
if(枚举TryParse(源,输出结果))
{
返回结果;
}
}
返回默认值;
}
}
我更新了地图,如下所示:
CreateMap<TaskDto, TaskModel>()
.ForPath(dest => dest.TaskType, opt => opt.MapFrom(src => src.TaskDefinition.TaskType.ToString()))
.ReverseMap()
.ForPath(dest => dest.TaskDefinition.TaskType, opt => opt.MapFrom(src => src.TaskType.ToTaskType()));
CreateMap()
.ForPath(dest=>dest.TaskType,opt=>opt.MapFrom(src=>src.TaskDefinition.TaskType.ToString())
.ReverseMap()
.ForPath(dest=>dest.TaskDefinition.TaskType,opt=>opt.MapFrom(src=>src.TaskType.ToTaskType());
与使用ForPath
相比,我更喜欢在同一配置文件中添加其他贴图。这样,我仍然可以使用自定义值解析程序:
public class DstObject
{
public int AnotherProperty { get; set; }
public DstChildObject DstChildObject { get; set; }
}
public class DstChildObject
{
public string SomeProperty { get; set; }
}
public class MyMappingProfile : Profile
{
public MyMappingProfile()
{
this.CreateMap<SourceType, DstObject>()
.ForMember(dst => dst.AnotherProperty, opt => opt.MapFrom(src => src.AnotherProperty))
.ForMember(dst => dst.DstChildObject, opt => opt.MapFrom(src => src))
;
this.CreateMap<SourceType, DstChildObject>()
.ForMember(dst => dst.SomeProperty, opt => opt.MapFrom(src => src.SomeProperty))
;
}
}
公共类对象
{
公共int其他属性{get;set;}
公共DstChildObject DstChildObject{get;set;}
}
公共类对象
{
公共字符串SomeProperty{get;set;}
}
公共类MyMappingProfile:Profile
{
公共MyMappingProfile()
{
这个
.ForMember(dst=>dst.AnotherProperty,opt=>opt.MapFrom(src=>src.AnotherProperty))
.ForMember(dst=>dst.dstchillobject,opt=>opt.MapFrom(src=>src))
;
这个
.FormMember(dst=>dst.SomeProperty,opt=>opt.MapFrom(src=>src.SomeProperty))
;
}
}
通过为内部对象创建映射,您始终可以避免路径问题。@LucianBargaoanu但如果它不是两个单独的对象,这是不可能的那么什么是Parent
?@LucianBargaoanu我们可以映射两个父对象,但是我们只需要父对象中的一个属性,而不需要完整的父对象,因此我们选择使用ForPath,否则我们必须在我们的模型中使用很多属性。所以在模型中,它不是一个单独的对象,只有一个属性ForPath
不支持转换器(除非您想自己实现)。因此,您要么使用MapFrom
,要么删除ForPath
。