AutoMapper.Mapper.CreateMap<TSource, TDestination>()已过时。

21
我有两个类似的类。
class A
{
 public int id {get; set;}
}

class B
{
 public C c {get; set;}
}

class C
{
 public int id {get; set;}
 public string Name {get; set;}
}

我的要求是将A类的id映射到C类的id。 直到现在我一直在做以下操作: Mapper.CreateMap().ForMember(des => des.C.Id, src => src.MapFrom(x => x.id));

它一直运行得很好。

现在似乎AutoMapper已经改变了实现方式。我收到了以下警告:

AutoMapper.Mapper.CreateMap()'已过时:'动态创建映射将在版本5.0中删除。使用MapperConfiguration实例并根据需要静态存储,或者使用Mapper.Initialize。使用CreateMapper创建一个映射器实例。

我需要映射具有不同名称和结构的类的某些属性。有关此事的任何帮助。


2
请查看这个帖子。 - diiN__________
1
@diiN_ 的评论应该会指引你正确的方向,但如果仍然遇到麻烦,你可以使用 NuGet 或命令提示符安装先前版本:Install-Package AutoMapper -Version 4.1.0。 - user964769
3个回答

33

以前

  Mapper.CreateMap<Src, Dest>()
 .ForMember(d => d.UserName, opt => opt.MapFrom(/* ????? */));

这里的问题是映射定义是静态的,只需在应用程序的生命周期内定义一次并重复使用。在3.3版本之前,您需要使用硬编码的值在每个请求上重新定义映射。由于映射配置是在与我们的映射执行不同的位置创建的,因此我们需要某种方式在配置中引入运行时参数,然后在执行期间提供它。

这需要分为两个部分来完成:我们创建一个运行时参数的映射定义,然后在执行时提供它。要使用运行时参数创建映射定义,我们“伪造”了一个包含命名本地变量的闭包:

Mapper.Initialize(cfg => {

string userName = null;
cfg.CreateMap<Source, Dest>()
    .ForMember(d => d.UserName, 
        opt => opt.MapFrom(src => userName)
    );
});

更多信息请参见此链接

适用于一个或多个类

 cfg.CreateMissingTypeMaps = true;
 cfg.CreateMap<Source, Dest>()
    .ForMember(d => d.UserName, 
        opt => opt.MapFrom(src => userName)
    );

 cfg.CreateMap<AbcEditViewModel, Abc>();
 cfg.CreateMap<Abc, AbcEditViewModel>();
});

在映射类中

  IMapper mapper = config.CreateMapper();
  var source = new AbcEditViewModel();
  var dest = mapper.Map<AbcEditViewModel, Abct>(source);

它运行良好,但之后出现了问题。如果两个类中具有完全相同的属性,则仅Mapper.map(Source,Destination)起作用,无需显式映射。 但是一旦我们使用了 Mapper.Initialize(cfg => { string userName = null; cfg.CreateMap() .ForMember(d => d.UserName, opt => opt.MapFrom(src => userName) );});没有其他Mapper.map(Source,Destination)可以工作(源和目标具有相同的属性和结构)。 - Sharad
你的源类和目标类是否是通用的?你必须为每个映射组合创建一个映射表。 - Anik Saha
你能给我展示一下你做了什么吗?展示代码。你在哪里创建地图,又在哪里进行映射?此外,我改进了我的答案。你是按照这种方式实现的吗? - Anik Saha
我面临的问题是,一旦我为两个具有不同属性和结构的映射器类实现了您建议的方法,它就可以正常工作。我将此代码添加到位于app_start文件夹中的.cs文件中,并在global.asax-->应用程序启动方法中将其注册到GlobalConfiguration.Configure()中。但是,如果以后我需要映射具有相似属性和结构的两个类,则该部分不起作用,而此前使用只需Mapper.Map(source,destination)行即可。 - Sharad
将代码添加到带有完整描述的问题中存在什么问题? - Anik Saha

5
另一种看起来比较干净的方式是创建一个 MappingProfile 类,该类继承自 AutoMapper 的 Profile 类。
public class MappingProfile:Profile
{
    public MappingProfile()
    {
        CreateMap<Source1, Destination1>();
        CreateMap<Source2, Destination2>();
        ...
    }
}

接下来,在你的启动代码中使用Mapper.Initialize(c => c.AddProfile<MappingProfile>());初始化映射。

这将使你能够在任何地方调用映射,例如:

destination1Collection = source1Collection.Select(Mapper.Map<Source1, Destination1>);

0

最终我找到了解决方案。我在App_start中执行了以下代码:Mapper.Initialize {从源到目标的映射字段},并将此文件添加到global.asax -> Application_Start() -> GlobalConfiguration。

我需要在我的Mapper.Initialize中再添加一行cfg.CreateMissingTypeMaps = true;

现在,这段代码将适用于显式映射,其中两个类具有不同的结构和属性名称。

除此之外,如果我们需要将两个具有相同结构的类的属性进行映射,则Mapper.map(source, destination)的代码也将起作用,而之前它无法正常工作。

如果有人对这个解决方案有困难,请告诉我。感谢以上回复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接