如何使用基本属性从 ViewModel 映射到模型
How to map from ViewModel to Model with base properties
我想将 ViewModel 映射到具有基础 class 的模型,但不将基础 class 添加到 ViewModel。
我想保留 classes 的结构。
我试过使用 Include、IncludeBase、IncludeDerivered,但找不到合适的配置。
这是我的代码
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]);
}
尽管调用了 MapFromAggregate,但对于派生属性 Automapper 可以正常工作,但基本属性未映射。
编辑
正如@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]);
}
我不知道为什么这个扩展方法会破坏我的代码。
问题是通用约束是针对 ICommand
而 setter 是针对 ICommand.AggregateId
的。您可以将约束更改为 Command
或为 ICommand.AggregateId
添加 setter。
我想将 ViewModel 映射到具有基础 class 的模型,但不将基础 class 添加到 ViewModel。
我想保留 classes 的结构。
我试过使用 Include、IncludeBase、IncludeDerivered,但找不到合适的配置。
这是我的代码
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]);
}
尽管调用了 MapFromAggregate,但对于派生属性 Automapper 可以正常工作,但基本属性未映射。
编辑
正如@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]);
}
我不知道为什么这个扩展方法会破坏我的代码。
问题是通用约束是针对 ICommand
而 setter 是针对 ICommand.AggregateId
的。您可以将约束更改为 Command
或为 ICommand.AggregateId
添加 setter。