自动映射:手动映射属性

kro*_*mbi 10 c# automapper

我刚开始使用automapper来映射DTO < - >实体,它似乎工作得很好.

在某些特殊情况下,我想只映射一些属性并执行其他检查.没有automapper,代码看起来像这样(使用fasterflect的PropertyExtensions):

object target;
object source;
string[] changedPropertyNames = { };

foreach (var changedPropertyName in changedPropertyNames)
{
    var newValue = source.GetPropertyValue(changedPropertyName);
    target.SetPropertyValue(changedPropertyName, newValue);
}
Run Code Online (Sandbox Code Playgroud)

当然,如果需要类型转换,此代码将不起作用.Automapper使用内置的TypeConverters,我还创建了一些特定的TypeConverter实现.

现在我想知道是否可以映射单个属性并使用automapper的类型转换实现,就像这样

Mapper.Map(source, target, changedPropertyName);
Run Code Online (Sandbox Code Playgroud)

更新

我认为有必要提供更多信息:

我已经创建了一些地图,例如

Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
Run Code Online (Sandbox Code Playgroud)

我还为CalendarEvent中的可为空的dateTime属性创建了一个带有自定义typeconverter的地图,例如

Mapper.CreateMap<DateTimeOffset?, DateTime?>().ConvertUsing<NullableDateTimeOffsetConverter>();
Run Code Online (Sandbox Code Playgroud)

我在web api OData Controller中使用这些映射.发布新的EntityDTO时,我使用

Mapper.Map(entityDto, entity);
Run Code Online (Sandbox Code Playgroud)

并将实体保存到数据存储区.

但是如果使用PATCH,则将a Delta<TDto> entityDto传递给我的控制器方法.因此,我需要entityDto.GetChangedPropertyNames()使用更改的值调用和更新现有的持久实体.

基本上这是使用我的简单解决方案,但如果其中一个更改的属性是例如DateTimeOffset?我想用我的NullableDateTimeOffsetConverter.

Pra*_*ana 22

如果您只想映射一些选择属性,而不是如下所示

// Create a map
var map = CreateMap<Source,Target>();
// ingnore all existing binding of property
map.ForAllMembers(opt => opt.Ignore());
// than map property as following
map.ForMember(dest => dest.prop1, opt => opt.MapFrom( src => src.prop1));
map.ForMember(dest => dest.prop2, opt => opt.MapFrom( src => src.prop2));
Run Code Online (Sandbox Code Playgroud)


Paw*_*aga 10

您可以使用MapFrom方法进行一些投影- http://automapper.readthedocs.io/en/latest/Projection.html

Mapper.Map(source, target)
   .ForMember(m => m.Property, opt => opt.MapFrom(src => src.ChangedProperty));
Run Code Online (Sandbox Code Playgroud)

例如(关注AutoMapper文档):

// Model
var calendarEvent = new CalendarEvent
    {
        Date = new DateTime(2008, 12, 15, 20, 30, 0),
        Title = "Company Holiday Party"
    };

// Configure AutoMapper
Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
    .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
    .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.Date.Hour))
    .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.Date.Minute));
Run Code Online (Sandbox Code Playgroud)


Ami*_*ari 5

要使用最新版本的AutoMapperfirst 执行此操作,您应该映射所需的属性,然后忽略其余属性。

CreateMap<TSource, TDestination>()
    .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.FirstName))
    .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"))
    .ForMember(dest => dest.Prop, opt => opt.MapFrom(src => src.AnotherProp))
    // ...
.ForAllOtherMembers(opt => opt.Ignore()); // <=== Ignore The rest
Run Code Online (Sandbox Code Playgroud)

否则,如果您map.ForAllMembers(opt => opt.Ignore());先这样做,它将忽略所有映射,甚至是此后的映射。