Configure a mapper from string to List<string> and from List<string> to string
I am trying to configure Napster of these two entities to pass from List to string but it gives me an error. any ideas. Thank you
public class EntidadVM
{ public List<string> CCC}
public class EntidadDto
{ public string CCC}
I'm doing them like this, but it gives me an error
TypeAdapterConfig<MailingDto, MailingVM>.NewConfig()
.Map(dest => dest.CCC, src => new List<string>(src.CCC.Split(',')).ToList() );
TypeAdapterConfig<MailingDto, MailingVM>.NewConfig()
.Map(dest => dest.CCC, src => src.CCC.Split(',').ToList() );
@ascariz
[TestMethod]
public void MapToTarget()
{
var dto = new EntidadDto { CCC = "one,two,three", };
// expression tree cannot contain call which contains optional arguments, so specify explicitly
var config = TypeAdapterConfig<EntidadDto, EntidadVM>.NewConfig()
.Map(dest => dest.CCC, src => new List<string>(src.CCC.Split(',', StringSplitOptions.None)).ToList());
var vm = dto.Adapt<EntidadVM>(config.Config);
vm.CCC.ShouldBe(new[] { "one", "two", "three" });
config = TypeAdapterConfig<EntidadDto, EntidadVM>.NewConfig()
.Map(dest => dest.CCC, src => src.CCC.Split(',', StringSplitOptions.None).ToList());
vm = dto.Adapt<EntidadVM>(config.Config);
vm.CCC.ShouldBe(new[] { "one", "two", "three" });
// or use after mapping
config = TypeAdapterConfig<EntidadDto, EntidadVM>.NewConfig()
.Ignore(x => x.CCC)
.AfterMapping((src, dest) => dest.CCC = src.CCC.Split(',').ToList());
vm = dto.Adapt<EntidadVM>(config.Config);
vm.CCC.ShouldBe(new[] { "one", "two", "three" });
config = TypeAdapterConfig<EntidadDto, EntidadVM>.NewConfig()
.Ignore(x => x.CCC)
.AfterMapping((src, dest) => dest.CCC = new List<string>(src.CCC.Split(',')).ToList());
vm = dto.Adapt<EntidadVM>(config.Config);
vm.CCC.ShouldBe(new[] { "one", "two", "three" });
}
And is it possible to map from List<string> to string? (The idea being, converting a list of strings to a string that contains each item separated by a comma.)
With this configuration:
TypeAdapterConfig<List<string>, string>
.NewConfig()
.Map(dest => dest, src => string.Join(", ", src));
When running this:
var list = new List<string> {"one", "two", "three"};
var result = list.Adapt<string>();
Then result contains System.Collections.Generic.List`1[System.String], instead of the expected "one, two, three".
According to the documentation:
When Mapster maps other types to string, Mapster will use
ToStringmethod
And that's what's happening.
Is it possible to override that behavior or do you recommend using something like an extension method on the List<string> type in this particular case?
@ignacioerrico In the documentation, it is mentioned that you need to use MapWith. Please refer to: https://github.com/MapsterMapper/Mapster/wiki/Custom-conversion-logic For more complex situations, you can always resort to building a LambdaExpression
E.g.
var c = x.When(argument => argument.DestinationType == typeof(string) && argument.SourceType == typeof(List<string>));
c.Settings.ConverterFactory = argument =>
{
var input = Expression.Parameter(typeof(List<string>), "list");
var joinMethod = typeof(string).GetMethod("Join", new[] { typeof(string), typeof(IEnumerable<string>) })
?? throw new InvalidOperationException("Method 'Join' not found.");
var delimiter = Expression.Constant(",", typeof(string));
var call = Expression.Call(joinMethod, delimiter, input);
var lambda = Expression.Lambda<Func<List<string>, string>>(call, input);
return lambda;
};
Thanks a lot for your prompt reply, @devbased. You may close this issue, since both directions have been covered (mapping from List<string> to string and vice versa).
@ignacioerrico I don't have the right to manage the issue 😅 It just turned out that I'm subscribed to this topic, so I quickly replied to you 😊