Skip to content

Can't map from IEnumerable<ISetting> when the underlying type is Setting[] - covariance issue? #3685

@lostllama

Description

@lostllama

Source/destination types

// Destination
public class Settings
{
	public string Test {get;set;}
}

// Source item
public interface ISetting
{
	string Name {get;set;}
	string Value {get;set;}
}

// Concrete source item
public class Setting : ISetting
{
	public string Name {get;set;}
	public string Value {get;set;}
}

Mapping configuration

var mc = new MapperConfiguration(cfg => {
    cfg.CreateMap<IEnumerable<ISetting>, Settings>()
        .ForMember(m => m.Test, o => o.MapFrom(c => c.FirstOrDefault(s => s.Name == "Test").Value)); 
});
		
var mapper = mc.CreateMapper();

Version

AutoMapper 10.1.1
.NET 5

Expected behavior

Mapping to succeed.

Actual behavior

AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping.
TypePair: Object -> Setting

Steps to reproduce

public static IEnumerable<ISetting> GetSettings()
{
	return new Setting[] { new Setting() { Name = "Test", Value = "Hello" } };
}

public static IEnumerable<ISetting> GetSettings2()
{
	return new ISetting[] { new Setting() { Name = "Test", Value = "Hello" } };
}

try
{
	Console.WriteLine();
	Console.WriteLine("As IEnumerable<ISetting>");
	Console.WriteLine();
	IEnumerable<ISetting> settings = GetSettings();
	Console.WriteLine($"Settings is {settings.GetType()}."); // prints Setting[]
	var result = mapper.Map<Settings>(settings);
	Console.WriteLine($"Success: Test is {result.Test}");
}
catch (AutoMapperMappingException e)
{
	var tp = (TypePair)e.Types;
	Console.WriteLine($"From {tp.SourceType} to {tp.DestinationType}"); // prints Object to Setting
	Console.WriteLine(e.ToString()); 
}

Console.WriteLine();
Console.WriteLine();

try
{
	Console.WriteLine();
	Console.WriteLine("As an array");
	Console.WriteLine();
	IEnumerable<ISetting> settings = GetSettings2();
	Console.WriteLine($"Settings is {settings.GetType()}."); // prints ISetting[]
	var result = mapper.Map<Settings>(settings);
	Console.WriteLine($"Success: Test is {result.Test}"); // prints Success: Test is Hello
}
catch (AutoMapperMappingException e)
{
	var tp = (TypePair)e.Types;
	Console.WriteLine($"From {tp.SourceType} to {tp.DestinationType}");
	Console.WriteLine(e.ToString());
}

This seems to be an issue related to IEnumerable<out T> being covariant.

Fiddle

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions