简体   繁体   中英

Empty property value after Automapper v5 upgrade

I have the below code that has been working in v3 of Automapper but no longer in v5. UPDATE It also works in v4.

CallScheduleProfile in its constructor sets a Title property to an instance of a class that passes a value of true to it.

CallScheduleProfileViewModel in its constructor sets a Title property to an instance of a different class that passes a value of true and "Title" .

I have setup the mappings in AutoMapper for all 4 classes and then I call Map.

The result is that the after the map the Title property on CallScheduleProfileViewModel has a boolean of true but FriendlyName is empty even though it's set in its constructor.

What I believe is happening is that the constructor on CallScheduleProfileViewModel is being called and FriendlyName is getting assigned but then when the mapping occurs it calls the constructor on Entry and then maps any properties on UxEntry that exist and assigns that to the Title property and by default FriendlyName will be null and because the FriendlyName doesn't exist on UxEntry its value isn't copied across.

I may be wrong in that assumption but either way how do I get FriendlyName populated on the mapping?

Update : I looked at Automapper documentation on nested types and the issue exists with code supplied in the docs too. If I add a string property to InnerDest and set its value in OuterDest constructor, after the Map its value is null.

public static void Main(string[] args)
{
    Mapper.Initialize(cfg =>
    {
        cfg.CreateMap<UxEntry<bool>, Entry<bool>>();

        cfg.CreateMap<CallScheduleProfile, CallScheduleProfileViewModel>();
    });

    var old = new CallScheduleProfile();

    var newmodel = Mapper.Map<CallScheduleProfile, CallScheduleProfileViewModel>(old);

    Console.WriteLine(newmodel.Title.Value);
    Console.WriteLine(newmodel.Title.FriendlyName);
}

public class UxEntry<T>
{
    public static implicit operator T(UxEntry<T> o)
    {
        return o.Value;
    }

    public UxEntry()
    {
        this.Value = default(T);
    }

    public UxEntry(T value)
    {
        this.Value = value;
    }

    public T Value { get; set; }
}


public class CallScheduleProfile
{
    public CallScheduleProfile()
    {
        this.Title = new UxEntry<bool>(true);
    }

    public UxEntry<bool> Title { get; set; }

}

public class Entry<T>
{
    public Entry()
    {
    }

    public Entry(T value, string friendlyName)
    {
        this.Value = value;
        this.FriendlyName = friendlyName;
    }

    public T Value { get; set; }
    public string FriendlyName { get; set; }

    public static implicit operator T(Entry<T> o)
    {
        return o.Value;
    }
}


public class CallScheduleProfileViewModel 
{
    public CallScheduleProfileViewModel()

    {
        this.Title = new Entry<bool>(true, "Title");
    }
    public Entry<bool> Title { get; set; }
}

Well, Automapper maps this property to null because :

A) Constructor for type Entry<T> set this property to null value

B) Automapper creates a new instance of Entry<T> after (!) the constructor in CallScheduleProfileViewModel is invoked.

C) There are no other rules set for Automapper

What you can do here is to change configuration, so that you let Automapper know that there should be a default value used for one of the properties :

        Mapper.Initialize(cfg =>
        {
            // when UxEntry is mapped to Entry value "Title" is used for property FriendlyName
            cfg.CreateMap<UxEntry<bool>, Entry<bool>>()
                .ForMember(dest => dest.FriendlyName, opt => opt.UseValue("Title"));

            cfg.CreateMap<CallScheduleProfile, CallScheduleProfileViewModel>();
        });

Now we can remove redundant property initialization from constructor in CallScheduleProfileViewModel .

Running your code without other changes produces following output :

true    
Title

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM