6

当我想使用UseDestinationValue方法中的行为时如何配置 AutoMapper 映射,但仅当目标属性为 NOT 时null

像这样的东西:

Mapper.CreateMap<Item, ItemViewModel>()
    .ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true))

编辑

class ItemDetails {
    public string Info { get; set; }
    public string ImportantData { get; set; } // only in Domain, not in ViewModel
}

class Item {
    public ItemDetails Details { get; set; }
}

class ItemDetailsViewModel {
    public string Info { get; set; }
}

class ItemViewModel {
    public ItemDetailsViewModel Details { get; set; }
}

现在使用示例。我有一个ItemViewModel班级,我想将它映射到Item班级。

映射配置:

    Mapper.CreateMap<Item, ItemViewModel>()
        .ForMember(x => x.Details, _ => _.UseDestinationValue())
  1. 第一种情况 - 目标属性Item.Details属性不为空。现在我希望 AutoMapper使用这个属性的目标实例Details,因为它不为空。

    逻辑如下所示:

    var item = new Item { 
        Details = new Details {
            Info = "Old text",
            ImportantData = "Data"
        }
    };
    
    var itemViewModel = new ItemViewModel { 
        Details = new DetailsViewModel {
            Info = "New text"
        }
    };       
    
    Mapper.Map(itemViewModel, item);
    

    AutoMapper,由于存在UseDestinationValue,将离开item.Details实例并仅设置item.Details.Info属性。

  2. 第二种情况 - 目标属性Item.Details属性为 NULL。现在我希望 AutoMapper不使用这个空实例,而是创建一个新实例。问题是如何配置映射以考虑这种情况?

    逻辑如下所示:

    var item = new Item { 
        Details = null
    };
    
    var itemViewModel = new ItemViewModel { 
        Details = new DetailsViewModel {
            Info = "New text"
        }
    };
    
    Mapper.Map(itemViewModel, item);
    

    问题

    这里我有一个问题,因为映射后,该item.Details属性将为空(因为在这种情况下使用UseDestinationValuenull)。

原因

NHibernate 从数据库中获取实体后,将其放入代理中。所以Details加载对象的属性不是 type: ItemDetails,而是ItemDetailsNHibernateProxy- 所以我必须使用这种类型,当我想稍后将这个现有对象保存到数据库中时。但是如果这个属性是null,那么我不能使用空目标值,所以 Automapper 应该创建一个新实例。

谢谢,克里斯

4

3 回答 3

2

有同样的问题,但使用 EF。Cryss 关于使用 BeforeMap 的评论为我指明了正确的方向。

我最终得到类似于以下的代码:

在 Configure() 方法中:

Mapper.CreateMap<ItemViewModel, Item>()
           .AfterMap((s, d) => { MapDetailsAction(s, d); })
           .ForMember(dest => dest.Details, opt => opt.UseDestinationValue());

然后行动:

Action<ItemViewModel, Item> MapDetailsAction = (source, destination) =>
        {
            if (destination.Details == null)
            {
                destination.Details = new Details();
                destination.Details =
                    Mapper.Map<ItemViewModel, Item>(
                    source.Details, destination.Details);
            }
        };
于 2015-02-16T10:48:30.420 回答
0

我认为该NullSubstitute选项对您有用。参见:http ://weblogs.asp.net/psteele/archive/2011/03/18/automapper-handling-null-members.aspx

编辑

看起来您可能需要为详细信息的映射添加一些条件逻辑(并跳过该UseDestinationValue选项):

.ForMember(d => d.Details, 
    o => o.MapFrom(s => s.Details == null ? new ItemDetails() : Mapper.Map<ItemDetailsViewModel, ItemDetails>(s.Details))
于 2012-09-11T15:00:41.220 回答
0

我在处理 NHibernate 实体时遇到了同样的问题,我找到了非常简单的解决方案。

您应该在 ItemViewModel 构造函数中初始化 Details 属性。这样,目标值永远不会为空。当然,这不适用于更复杂的情况(如抽象类)。

于 2012-11-14T08:26:59.603 回答