Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
705 views
in Technique[技术] by (71.8m points)

c# - UseDestinationValue only when destination property is not null

How to configure AutoMapper mapping when I want to use behaviour from UseDestinationValue method, but only when destination property is NOT null.

Something like that:

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

EDIT

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; }
}

Now example of usage. I have a ItemViewModel class and I want to map it to the Item class.

Mapping configuration:

    Mapper.CreateMap<Item, ItemViewModel>()
        .ForMember(x => x.Details, _ => _.UseDestinationValue())
  1. First case - destination property Item.Details property is NOT NULL. Now I want AutoMapper to use this destination instance of Details property, because it's not null.

    And the logic looks like this:

    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, because of presence of UseDestinationValue, will leave the item.Details instance and set only item.Details.Info property.

  2. Second case - destination property Item.Details property is NULL. Now I want AutoMapper not to use this null instance, but create new one. The question is how to configure the mapping to take into account this case?

    The logic looks like this:

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

    PROBLEM

    Here I have a problem, because after mapping, the item.Details property will be null (because of usage of UseDestinationValue which is null in this case).

REASON

NHibernate, after getting the entity from the database, puts it into a proxy. So the Details property of a loaded object is not of a type: ItemDetails, but ItemDetailsNHibernateProxy - so I have to use this type, when I want to save this existing object to the database later. But if this property is null, then I can't use a null destination value, so Automapper should create a new instance.

Thanks, Chris

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Had this same problem, but with EF. Cryss' comment about using BeforeMap pointed me in the right direction.

I ended up with code similar to:

In the Configure() method:

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

Then the Action:

Action<ItemViewModel, Item> MapDetailsAction = (source, destination) =>
        {
            if (destination.Details == null)
            {
                destination.Details = new Details();
                destination.Details =
                    Mapper.Map<ItemViewModel, Item>(
                    source.Details, destination.Details);
            }
        };

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...