HaMEd
HaMEd

Reputation: 43

Automapper The interface has a conflicting property ID Parameter name: interfaceType

This is my model Heirarchy :

public interface INodeModel<T> : INodeModel
where T : struct
{
    new T? ID { get; set; }
}

public interface INodeModel
{
    object ID { get; set; }
    string Name { get; set; }
}

public class NodeModel<T> : INodeModel<T>
 where T : struct
{
    public T? ID { get; set; }
    public string Name { get; set; }

    object INodeModel.ID
    {
        get
        {
            return ID;
        }

        set
        {
            ID = value as T?;
        }
    }
}

public class NodeDto<T> where T : struct
{
    public T? ID { get; set; }
    public string Name { get; set; }
}

and these are my mappings and test :

    class Program
{
    private static MapperConfiguration _mapperConfiguration;

    static void Main(string[] args)
    {
        _mapperConfiguration = new MapperConfiguration(cfg =>
        {

            cfg.CreateMap(typeof(NodeDto<>), typeof(NodeModel<>));
            cfg.CreateMap(typeof(NodeDto<>), typeof(INodeModel<>));
            cfg.CreateMap(typeof(INodeModel<>), typeof(NodeModel<>));

        });

        var dto = new NodeDto<int> { ID = 1, Name = "Hi" };

        var obj = _mapperConfiguration.CreateMapper().Map<INodeModel<int>>(dto);


        Console.Write(obj.ID);
        Console.ReadLine();
    }
}

and here is the exception :

AutoMapper.AutoMapperMappingException:

Mapping types:

NodeDto1 -> INodeModel1 NodeDto`1[[System.Int32] ->

INodeModel`1[[System.Int32]

Message:

The interface has a conflicting property ID Parameter name: interfaceType

Stack:

at AutoMapper.Internal.ProxyGenerator.CreateProxyType(Type interfaceType)

at AutoMapper.Internal.ProxyGenerator.GetProxyType(Type interfaceType)

at AutoMapper.MappingEngine.CreateObject(ResolutionContext context)

Upvotes: 1

Views: 373

Answers (1)

Jimmy Bogard
Jimmy Bogard

Reputation: 26775

AutoMapper is confused when creating a proxy implementation that you have two members with the same name in your interfaces. You're using shadowing, which is even harder. Rather than assume AutoMapper can make sense of this, which, good luck explaining to a new team member, I would instead make the interface class implementation explicit:

cfg.CreateMap(typeof(NodeDto<>), typeof(NodeModel<>));
cfg.CreateMap(typeof(NodeDto<>), typeof(INodeModel<>))
    .ConvertUsing(typeof(NodeModelConverter<>));
cfg.CreateMap(typeof(INodeModel<>), typeof(NodeModel<>));

public class NodeModelConverter<T> :
    ITypeConverter<NodeModel<T>, INodeModel<T>> where T : struct
{
    public INodeModel<T> Convert(NodeModel<T> source, ResolutionContext context)
         => new NodeModelImpl {ID = source.ID, Name = source.Name};

    private class NodeModelImpl : INodeModel<T>
    {
        public T? ID { get; set; }

        public string Name { get; set; }

        object INodeModel.ID
        {
            get { return ID; }

            set { ID = (T?) value; }
        }
    }
}

No magic and completely explicit and obvious!

Upvotes: 1

Related Questions