将通用IEnumerable映射到通用List时,Automapper失败

时间:2014-06-14 06:30:28

标签: c# wcf fluent-nhibernate automapper

我在SO +谷歌中搜索了所提到的问题,我经历了所有SO问题,但没有得到我的问题的解决方案。

这是我的问题:我在尝试使用List prop 映射 IEnumerable prop时, AutoMapper.AutoMapperConfigurationException

这是片段:

//Logical
public class TestClassPLogical
{
    public List<TestClassLogical> TestProp
    {
        get;
        set;
    }
}

public class TestClassLogical
{
    //defined prop
}

//Model

public class TestClassPDto
{
    public virtual IEnumerable<TestClassDto> TestProp
    {
        get;
        set;
    }
}

public class TestClassDto
{
    //defined prop
}

//Mapping

public class TestClassMapper
{
    public static void Configure()
    {
        //ToDto
        Mapper.CreateMap<TestClassPDto, TestClassPLogical>()
             .ForMember(d => d.TestProp,
             o => o.MapFrom(s => AutoMapperExtensions.MapIEnumerableToList(s.TestProp)));

        //ToLogical
        Mapper.CreateMap<TestClassPLogical, TestClassPDto>()
            .ForMember(d => d.TestProp, o => o.MapFrom(s => AutoMapperExtensions.MapListToIEnumerable(s.TestProp)));

    }
}

//Custom class

public class CustomMapperExtensions
{
    public static List<T> MapIEnumerableToList<T>(IEnumerable<T> source) where T : class
    {
        return source == null
            ? new List<T>()
            : source.ToList();
    }

    public static IEnumerable<T> MapListToIEnumerable<T>(List<T> source) where T : class
    {
        return source.Count > 0
            ? source.ToList()
            : new List<T>();
    }
}

//Unit Test

public class TestClassMapperTest
{
    [TestFixtureSetUp]
    public void Setup()
    {
        TestClassMapper.Configure();
    }

    [Test]
    public void EnsureFieldsAreAllMappedOrIgnored()
    {
        Mapper.AssertConfigurationIsValid();
    }
}

P.S。:我们使用Fluent Nhibernate作为ORM。

以下是例外:

  

AutoMapper.AutoMapperConfigurationException:以下属性   在TestClassPLogical上无法映射: TestProp 添加一个   自定义映射表达式,忽略,添加自定义解析程序或修改   目标类型TestClassLogical。

任何帮助解决上述问题的人都将非常感激。

更新 我已经尝试使用ReverseMap(),这是抛出相同的异常,这里是片段:

//Mapping

public class TestClassMapper
{
    public static void Configure()
    {
        //ToDto
        Mapper.CreateMap<TestClassPDto, TestClassPLogical>()
             .ForMember(d => d.TestProp,
             o => o.MapFrom(s => AutoMapperExtensions.MapIEnumerableToList(s.TestProp)));

        Mapper.CreateMap<TestClassDto, TestClassLogical>().ReverseMap();

        //ToLogical
        Mapper.CreateMap<TestClassPLogical, TestClassPDto>()
            .ForMember(d => d.TestProp, o => o.MapFrom(s => AutoMapperExtensions.MapListToIEnumerable(s.TestProp)));

        Mapper.CreateMap<TestClassLogical, TestClassDto>().Reverse();

    }
}

例外是:

  

AutoMapper.AutoMapperConfigurationException:以下属性   在TestClassPLogical上无法映射:

     

TestProp

     

添加自定义映射表达式,忽略,添加自定义解析程序或   修改目标类型TestClassLogical。上下文:映射到   属性TestProp从TestClassDto到TestClassLogical映射到   属性TestProp来自   System.Collections.Generic.List 1[[TestClassDto, TestMapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] to System.Collections.Generic.List 1 [[TestClassLogical,TestMapper,   Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]   键入TestClassPDto到ClassPLogical类型的异常   抛出'AutoMapper.AutoMapperConfigurationException'。在   AutoMapper.ConfigurationStore.DryRunTypeMap(ICollection 1 typeMapsChecked, ResolutionContext context) at AutoMapper.ConfigurationStore.DryRunTypeMap(ICollection 1 typeMapsChecked,ResolutionContext context)   在   AutoMapper.ConfigurationStore.DryRunTypeMap(ICollection 1 typeMapsChecked, ResolutionContext context) at AutoMapper.ConfigurationStore.AssertConfigurationIsValid(IEnumerable 1 typeMaps)   在AutoMapper.ConfigurationStore.AssertConfigurationIsValid()at   AutoMapper.Mapper.AssertConfigurationIsValid()

2 个答案:

答案 0 :(得分:1)

你要做的比实际要困难得多。只需映射您需要的所有类对,AutoMapper就能将嵌套的源集合映射到嵌套的目标集合。

在Linqpad中看到这个小例子(我使用了一些不那么混乱的名字):

void Main()
{
    Mapper.CreateMap<Parent,ParentDto>().ReverseMap();
    Mapper.CreateMap<Child,ChildDto>().ReverseMap();
    Mapper.AssertConfigurationIsValid();

    var par = new Parent { TestProp = new List<Child> 
                           { new Child(),
                             new Child() 
                           }
                         };
    Mapper.Map<ParentDto>(par).Dump();
    Mapper.Map<Parent>(Mapper.Map<ParentDto>(par)).Dump();
}

class Parent
{
    public List<Child> TestProp{ get; set; }
}
class Child {}

class ParentDto
{
    public IEnumerable<ChildDto> TestProp{ get; set; }
}
class ChildDto {}

Dump陈述的输出:

ParentDto
 - ChildDto 
 - ChildDto 

Parent
 - Child 
 - Child 

答案 1 :(得分:1)

我在了解了ReverseMap()&#39;完全一样。

我将Map TestClass 映射为:

public class TestClassMapper
        {
            public static void Configure()
            {
                //ToDto
                Mapper.CreateMap<TestClassDto, TestClassPLogical>();

                //ToLogical
                Mapper.CreateMap<TestClassLogical, TestClassDto>();
            }
        }

现在,每当我尝试反击地图()&#39;正如@Gert Arnold所建议的那样,它调用了两次映射,一个是ReverseMap,另一个是Configure()方法,这打破了一切。

P.S。:我有很多子课,比如

TestClassPLogical 
  TestClassLogical 
  TestClass1Logical 
  TestClass2Logical
  TestClass3Logical

以下是我更改的代码段:

public class TestClassPMapper
        {
            public static void Configure()
            {
                //ToDto
                Mapper.CreateMap<TestClassPDto, TestClassPLogical>();

                //ToLogical
                Mapper.CreateMap<TestClassPLogical, TestClassPDto>();

                //What I changed
                TestClassMapper.Configure();

            }
        }

以下代码正常运行,当我删除Configure()方法并拨打电话时如下:

Mapper.CreateMap<TestClassPDto, TestClassPLogical>().ReverseMap()
Mapper.CreateMap<TestClassDto, TestClassLogical>().ReverseMap()

P.S。

  • 现在进行上述更改,即使它是映射道具也不需要 通用IEnumerable&lt; =&gt;列表。
  • 我只需要为那些需要某种自定义的成员/道具使用.MapFrom(),例如我需要映射Full_Name,这应该是First_Name + ' ' + Last_Name

最后,我的单元测试通过了:)

public class TestClassMapperTest
        {
            [TestFixtureSetUp]
            public void Setup()
            {
                TestClassMapper.Configure();
            }

            [Test]
            public void EnsureFieldsAreAllMappedOrIgnored()
            {
                Mapper.AssertConfigurationIsValid();
            }
        }