AutoMapper: Map Interface to Abstract class - is this possible?

梦想与她 提交于 2019-12-07 05:09:40

问题


I'm using AutoMapper to map objects between different layers of my application. On the one side I have an interface which looks like this:

public interface MyRepo 
{
    IEnumerable<IRootObject> GetItems(param);
}

IRootObject looks like this:

public interface IRootObject
{
    int Id { get; set; }
    DateTime? Date { get; set; }
}

public interface IFirstSubObject : IRootObject 
{
    string MyFirstProp { get; set; }
}

public interface ISecondSubObject : IRootObject 
{
    string MySecondProp { get; set; }
}

So the GetItems()call actually returns an array of only IxxxSubObjectItems. On the other side the structure looks like this:

public abstract class MyCustomRoot
{
    protected MyCustomRoot(){}
    public int Id { get; set; }
    public DateTime? Date { get; set; }
}

public class MyCustomFirstSub : MyCustomRoot
{
    public MyCustomFirstSub() : base() {} 
    public string MyFirstProp { get; set; }
}

public class MyCustomSecondSub : MyCustomRoot
{
    public MyCustomSecondSub () : base() {} 
    public string MySecondProp { get; set; }
}

Now I've set up the mapper like so

AutoMapper.Mapper.CreateMap<IRootObject, MyCustomRoot>
    .Include<IFirstSubObject, MyCustomFirstSub>
    .Include<ISecondSubObject, MyCustomSecondSub>();

AutoMapper.Mapper.CreateMap<IFirstSubObject, MyCustomFirstSub>();
AutoMapper.Mapper.CreateMap<ISecondSubObject, MyCustomSecondSub>();

But I keep getting MapperExceptions ("Cannot construct abstract class", which makes sense in a way). I also call AssertConfigurationIsValid, and that passes for this code.
If I don't make the MyCustomRoot class abstract, then the mapping works, but I get a list of MyCustomRoot objects, while I actually would like to have a list of MyCustomxxxSub, because there is a Factory later on which uses this type to generate the correct UI...

I hope someone can point me in the right direction for this one!
Thanks!


回答1:


Ok I found a way to actually do this! So with the Interfaces and Classes provided above, you can do something like this
(Remember: the MyCustomRoot class is abstract)

AutoMapper.Mapper.CreateMap<IRootObject, MyCustomRoot>
    .Include<IFirstSubObject, MyCustomFirstSub>
    .Include<ISecondSubObject, MyCustomSecondSub>();

and then use the followig Map call to map the objects:

public List<MyCustomRoot> PerformMapping(List<IRootObject> rootObjects)
{
    var returnList = new List<CustomRoot>();
    foreach(var rootObject in rootObjects)
    {
        var abstractObject = (MyCustomRoot)Mapper.Map(rootObject, rootObject.GetType(), typeof(MyCustomRoot));
        returnList.Add(abstractObject);
    }
    return returnList;
}

Now I actually get an array of MyCustomRoot objects, which are all the specific implementations.

This is exactly what I was looking for!




回答2:


If so, then you want to map to that factory, inject it and let it create the correct instance in due time, since it's the factory that apparently knows what to instantiate.



来源:https://stackoverflow.com/questions/5578253/automapper-map-interface-to-abstract-class-is-this-possible

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!