MapsterMapper / Mapster

A fast, fun and stimulating object to object Mapper
MIT License
4.23k stars 325 forks source link

Struggling with mapping readonly ICollection property #689

Open akordowski opened 3 months ago

akordowski commented 3 months ago

Discussed in https://github.com/MapsterMapper/Mapster/discussions/688

Originally posted by **akordowski** March 24, 2024 Hi everyone! I am currently struggling with the mapping of a readonly ICollection property. I followed the [instructions](https://github.com/MapsterMapper/Mapster/wiki/Mapping-readonly-prop) but I can't make it work. The readonly collection is not populated with the mapped content. What am I making wrong? Have anyone an idea how I can make it work? Here the code: **Programm.cs** ``` var config = TypeAdapterConfig.GlobalSettings; config.Scan(typeof(ChannelMapping).Assembly); config.Default.UseDestinationValue(m => m.SetterModifier == AccessModifier.None && m.Type.IsGenericType && m.Type.GetGenericTypeDefinition() == typeof(ICollection<>)); var channelSrc = new MapsterTest.Objects.Source.Channel { ChannelId = "123", Thumbnails = new MapsterTest.Objects.Source.ThumbnailDetails { Default = new MapsterTest.Objects.Source.Thumbnail { Url = "https://www.youtube.com/default.jpg" }, Medium = new MapsterTest.Objects.Source.Thumbnail { Url = "https://www.youtube.com/medium.jpg" }, High = new MapsterTest.Objects.Source.Thumbnail { Url = "https://www.youtube.com/high.jpg" } } }; // Thumbnails are mapped correctly to a collection var thumbnailsDest = channelSrc.Thumbnails.Adapt>().ToList(); // channelDest.Thumbnails collection is empty var channelDest = channelSrc.Adapt(); ``` **ThumbnailMapping.cs** ``` public class ThumbnailMapping : IRegister { public void Register(TypeAdapterConfig config) { config.ForType>() .MapWith(src => MapThumbnailDetails(src).ToList()); } private static IEnumerable MapThumbnailDetails(Objects.Source.ThumbnailDetails thumbnailDetails) { yield return MapThumbnail(thumbnailDetails.Default, "Default"); yield return MapThumbnail(thumbnailDetails.Medium, "Medium"); yield return MapThumbnail(thumbnailDetails.High, "High"); } private static Objects.Destination.Thumbnail MapThumbnail( Objects.Source.Thumbnail thumbnail, string thumbnailType) => new() { Type = thumbnailType, Url = thumbnail.Url.Trim(), }; } ``` **Channel.cs (Destination)** ``` public class Channel { public string ChannelId { get; set; } = default!; public ICollection Thumbnails { get; } = new List(); } ``` **Thumbnail.cs (Destination)** ``` public class Thumbnail { public string Type { get; set; } = default!; public string Url { get; set; } = default!; } ``` **Channel.cs (Source)** ``` public class Channel { public string ChannelId { get; set; } = default!; public ThumbnailDetails Thumbnails { get; set; } = default!; } ``` **ThumbnailDetails.cs (Source)** ``` public class ThumbnailDetails { public Thumbnail? Default { get; set; } public Thumbnail? Medium { get; set; } public Thumbnail? High { get; set; } } ``` **Thumbnail.cs (Source)** ``` public class Thumbnail { public string Url { get; set; } = default!; } ```