c# - 如何从 ViewModel 映射到具有基本属性的模型
问题描述
我想将 ViewModel 映射到具有基类的模型,但不向 ViewModel 添加基类。
我想保持我的班级结构。
我曾尝试使用 Include、IncludeBase、IncludeDerived,但找不到好的配置。
这是我的代码
public class Program
{
private static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var mapper = new MapperConfiguration(mc => mc.AddProfile(new MappingProfile())).CreateMapper();
var model = new RegisterViewModel { Name = "TEST" };
var x = mapper.Map<Register>(model, Guid.NewGuid());
}
}
public interface ICommand
{
Guid Id { get; }
Guid AggregateId { get; }
}
public abstract class Command : ICommand
{
protected Command() => Id = Guid.NewGuid();
public Guid Id { get; }
public Guid AggregateId { get; private set; }
}
public sealed class Register : Command
{
public string Name { get; private set; }
}
public class RegisterViewModel
{
public string Name { get; set; }
}
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<RegisterViewModel, Command>()
.ForMember(x => x.Id, opt => opt.Ignore())
.AddCommandFields()
.Include<RegisterViewModel, Register>();
CreateMap<RegisterViewModel, Register>().IncludeBase<RegisterViewModel, Command>().AddCommandFields();
}
}
public static class MapperExtensions
{
private static readonly string AGGREGATE_KEY = "AGGREGATE";
public static TDestination Map<TDestination>(this IMapper mapper, object source, Guid aggregateId)
{
return mapper.Map<TDestination>(source, opt =>
{
opt.Items[AGGREGATE_KEY] = aggregateId;
});
}
public static IMappingExpression<TSource, TDestination> AddCommandFields<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
where TDestination : ICommand => expression.ForMember(x => x.AggregateId, opt => opt.MapFromAggregate());
private static void MapFromAggregate<TSource, TDestination>(this IMemberConfigurationExpression<TSource, TDestination, Guid> expression) => expression.MapFrom((_, __, ___, context) => context.Items[AGGREGATE_KEY]);
}
对于派生属性 Automapper 可以正常工作,但未映射基本属性,尽管调用了 MapFromAggregate。
编辑
正如@Lucian Bargaoanu 建议的那样,我想删除扩展方法,但后来我发现问题出在方法“AddCommandFields”上。
此代码正常工作
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<RegisterViewModel, Command>()
.ForMember(x => x.Id, opt => opt.Ignore())
.ForMember(x => x.AggregateId, opt => opt.MapFromAggregate())
.Include<RegisterViewModel, Register>();
CreateMap<RegisterViewModel, Register>()
.IncludeBase<RegisterViewModel, Command>()
.ForMember(x => x.AggregateId, opt => opt.MapFromAggregate());
}
}
public static class MapperExtensions
{
private static readonly string AGGREGATE_KEY = "AGGREGATE";
public static TDestination Map<TDestination>(this IMapper mapper, object source, Guid aggregateId)
{
return mapper.Map<TDestination>(source, opt =>
{
opt.Items[AGGREGATE_KEY] = aggregateId;
});
}
public static void MapFromAggregate<TSource, TDestination>(this IMemberConfigurationExpression<TSource, TDestination, Guid> expression) => expression.MapFrom((_, __, ___, context) => context.Items[AGGREGATE_KEY]);
}
我不知道为什么这个扩展方法会破坏我的代码。
解决方案
问题是通用约束是 forICommand
并且没有 setter for ICommand.AggregateId
。您可以将约束更改为Command
或添加设置器ICommand.AggregateId
。
推荐阅读
- sql - 如果前一个发现任何东西,Sql server 阻止下一个加入
- python - 用户关键字的 robots.running.model.Keyword 对象子属性在 prerunmodifier start_suite 函数中返回空列表
- drupal - 在树枝模板中包含 Drupal 分类术语链接
- angularjs - 如何在 Promise.race() 中设置超时?
- javascript - 是否可以在处理函数中删除和读取 React eventListener?
- cypress - cypress headless 中的测试运行给出错误 cy.click()
- reactjs - 找不到模块:无法解析“./containers”
- html - CSS 三张图片淡入动画时长
- reactjs - 为什么 React.StrictMode 会改变组件的行为?
- nmcli - 设备的 MAC 和连接不匹配