AutoMapper和AutoFixture中的冲突

AutoMapper和AutoFixture中的冲突,automapper,autofixture,Automapper,Autofixture,我有2个类,Class1应该映射到Class2。我使用自动映射器进行映射。我想测试映射器的配置,为此,我使用了自动夹具。源类Class1具有IList类型的属性,目标类Class2具有类似的属性,但类型为IEnumerable。为了简化测试准备,我使用了自动夹具(带有自动moqcustomization)来初始化源对象和目标对象。但在使用AutoFixture初始化IEnumerable类型的属性后,AutoMapper无法映射该属性 错误文本: 映射类型时出错 映射类型:Class1->Cla

我有2个类,Class1应该映射到Class2。我使用自动映射器进行映射。我想测试映射器的配置,为此,我使用了自动夹具。源类Class1具有IList类型的属性,目标类Class2具有类似的属性,但类型为IEnumerable。为了简化测试准备,我使用了自动夹具(带有自动moqcustomization)来初始化源对象和目标对象。但在使用AutoFixture初始化IEnumerable类型的属性后,AutoMapper无法映射该属性

错误文本:

映射类型时出错

映射类型:Class1->Class2 ConsoleApplication1.Class1-> 控制台应用程序1.Class2

类型映射配置:Class1->Class2控制台应用程序1.Class1-> 控制台应用程序1.Class2

属性:项目

有谁能帮我配置AutoMapper或AutoFixture使映射工作?作为一种解决方法,我可以将null分配给destination属性,但我不希望在每次测试中都这样做

代码的简化示例:

public class AutoMapperTests
{
    public static void TestCollectionsProperty()
    {
        Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<ItemClass1, ItemClass2>();
            cfg.CreateMap<Class1, Class2>();
        });

        var src = new Class1();
        src.Items = new List<ItemClass1>()
        {
            new ItemClass1() { Text = "111" },
            new ItemClass1() { Text = "222" }
        };

        var fixture = new Fixture();
        var dst = fixture.Create<Class2>();

        Mapper.Map(src, dst); //Error at this line of code
    }
}

public class Class1
{
    public IList<ItemClass1> Items { get; set; }
}

public class Class2
{
    public IEnumerable<ItemClass2> Items { get; set; }
}

public class ItemClass1
{
    public string Text { get; set; }
}
public class ItemClass2
{
    public string Text { get; set; }
}
公共类测试
{
公共静态void TestCollectionsProperty()
{
Mapper.Initialize(cfg=>
{
CreateMap();
CreateMap();
});
var src=new Class1();
src.Items=新列表()
{
新的ItemClass1(){Text=“111”},
新的ItemClass1(){Text=“222”}
};
var fixture=新fixture();
var dst=fixture.Create();
Mapper.Map(src,dst);//此代码行出错
}
}
公共班级1
{
公共IList项{get;set;}
}
公共课2
{
公共IEnumerable项{get;set;}
}
公共类项目类别1
{
公共字符串文本{get;set;}
}
公共类ItemClass2
{
公共字符串文本{get;set;}
}

以下是解决您的问题的一个有效示例。正如@markseemann已经告诉我们的,
Mapper.CreateMap
已经被弃用,所以这个例子使用了新的结构

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<ItemClass1, ItemClass2>();
    cfg.CreateMap<Class1, Class2>();
});

var src = new Class1();
src.Items = new List<ItemClass1>()
{
    new ItemClass1() { Text = "111" },
    new ItemClass1() { Text = "222" }
};

var dest = Mapper.Map<Class1, Class2>(src);
Mapper.Initialize(cfg=>
{
CreateMap();
CreateMap();
});
var src=new Class1();
src.Items=新列表()
{
新的ItemClass1(){Text=“111”},
新的ItemClass1(){Text=“222”}
};
var dest=Mapper.Map(src);

这本身并不是一个真正的自动夹具问题。您可以在不使用AutoFixture的情况下复制它,方法是创建
dst
这样:

var dst = new Class2();
dst.Items = Enumerable.Range(0, 1).Select(_ => new ItemClass2());
var dst = fixture.Build<Class2>().OmitAutoProperties().Create();
var dst = fixture.Create<Class2>();
dst.Items = dst.Items.ToList();
这将产生类似的错误消息:

无法将类型为“WhereSelectEnumerableTerator
2[System.Int32,Ploeh.StackOverflow.Q45437098.ItemClass2]”的对象强制转换为类型为“System.Collections.Generic.IList
1[Ploeh.StackOverflow.Q45437098.ItemClass2]”

这应该是不言自明的:
WhereSelectEnumerableIterator
不实现
IList
。AutoMapper试图进行该转换,但失败了

最简单的修复方法可能是避免填充
dst

var dst = new Class2();
如果必须使用AutoFixture进行此操作,可以按如下方式进行:

var dst = new Class2();
dst.Items = Enumerable.Range(0, 1).Select(_ => new ItemClass2());
var dst = fixture.Build<Class2>().OmitAutoProperties().Create();
var dst = fixture.Create<Class2>();
dst.Items = dst.Items.ToList();

您可以创建一个自定义项以确保自动执行此操作,但如果需要帮助,请提出一个新问题(如果您没有找到一个已经回答该问题的问题)。

AM需要IList,因为您正在映射到现有列表,并且可以通过调用IList.Add来工作。

发布的代码不会编译,因为(AFICT)
Mapper.CreateMap
已被弃用并从AutoMapper中删除。请更新复制代码,或发布正在使用的NuGet软件包列表,包括它们的版本号。感谢您的评论,我已经更新了示例谢谢您的回答,但问题是我需要使用void方法Mapper.Map(src,dst);但它不起作用。当我使用返回目标对象的方法时,即使在旧版本的AutoMaper中CreateMap是Mapper类的静态方法,一切都可以正常工作。