C# 自动映射如何根据上下文将对象A映射到对象B

C# 自动映射如何根据上下文将对象A映射到对象B,c#,automapper,C#,Automapper,呼叫所有汽车制造商大师 我希望能够根据运行时的上下文,以不同的方式将对象A映射到对象B。特别是,我希望在一种映射情况下忽略某些属性,而在另一种情况下映射所有属性 我所经历的是,在不同的映射情况下可以成功调用Mapper.CreateMap,但是,一旦调用了CreateMap,就会设置特定类型对的映射,并且随后不会通过后续的CreateMap调用进行更改,这可能会以不同的方式描述映射 我发现了一篇提倡Mapper.Reset()的博客文章来解决这个问题,然而,Mapper类的静态特性意味着碰撞和崩

呼叫所有汽车制造商大师

我希望能够根据运行时的上下文,以不同的方式将对象A映射到对象B。特别是,我希望在一种映射情况下忽略某些属性,而在另一种情况下映射所有属性

我所经历的是,在不同的映射情况下可以成功调用Mapper.CreateMap,但是,一旦调用了CreateMap,就会设置特定类型对的映射,并且随后不会通过后续的CreateMap调用进行更改,这可能会以不同的方式描述映射

我发现了一篇提倡Mapper.Reset()的博客文章来解决这个问题,然而,Mapper类的静态特性意味着碰撞和崩溃发生只是时间问题

有办法做到这一点吗

我想我需要的是在每个appdomain中调用Mapper.CreateMap一次,然后再调用Mapper.Map,并提示应该包含/排除哪些属性

现在,我正在考虑通过编写一个非静态映射类来更改源代码,该类保存基于实例的映射配置。性能差,但线程安全


我的选择是什么。可以做些什么?Automapper看起来很有前途。

映射器类只是配置和映射引擎对象之上的一个薄包装器。您可以创建Configuration/MappingEngine对象的单独实例(仍然使用单例),并根据需要使用您选择的IoC容器加载正确的实例


最好的选择仍然是使用不同的目的地类型。真正支持此功能的真正困难之处在于类型映射固有的层次性。顶级对象可能有映射配置文件,而低级对象则没有。介于两者之间的一些可能拥有或没有,等等。

对我来说,更好的设计可能是拥有多个目标类(可能从公共基继承或实现公共接口)

如果未映射属性永远不会在其中一个变体中使用,则可以完全忽略它们(提供编译时保证不会错误使用它们),在访问它们时抛出异常(不如编译时保证好,但有时需要实现完整的接口)或者甚至使用替代值

例如:

public class Source
{
    public string Name {get;set;}
    public BigEntity {get;set;}

    /* other members */
}

public class SourceDTO
{
    public string Name {get;set;}
    public BigEntity {get;set;}
}

public class SourceSummaryDTO
{
    public string Name {get;set;}
}
或者,您可以这样做:

public class SourceSummaryDTO : SourceDTO
{
    public string Name {get;set;}
    public BigEntity 
    {
        get{throw new NotSupportedException();}
        set{throw new NotSupportedException();}
    }
}
这样,您就可以像传递SourceSummaryDTO一样传递SourceSummaryDTO

对我来说,有条件地填充属性听起来像是一个麻烦的秘诀——我更希望有明确说明其包含内容的类,尤其是数据传输对象


对我来说,Automapper最好的功能是验证映射,然后知道目标类上的每个属性都将被填充。

为了补充Jimmy的答案,下面是在没有静态映射器的情况下使用Automapper所需的代码

自4.2.1版起,Automapper具有经认可的非静态映射器和配置(谢谢Jimmy!)

var config=new-MapperConfiguration(cfg=>{
CreateMap();
});
var mapper=config.CreateMapper();
新版本中还有许多其他有用的选项(例如概要文件)用于创建不同的映射器实例。 你可以在网站上找到所有的细节

(适用于4.1.1版)

//配置
AutoMapper.Mappers.MapperRegistry.Reset();
var autoMapperCfg=new AutoMapper.ConfigurationStore(new TypeMapFactory(),AutoMapper.Mappers.MapperRegistry.Mappers);
var mappingEngine=new AutoMapper.mappingEngine(autoMapperCfg);
autoMapperCfg.Seal();
//用法示例
autoMapperCfg.CreateMap();
var b=映射引擎.Map(a);
(适用于3.2.1版)

//配置
var platformSpecificRegistry=AutoMapper.Internal.PlatformAdapter.Resolve();
platformSpecificRegistry.Initialize();
var autoMapperCfg=new AutoMapper.ConfigurationStore(new TypeMapFactory(),AutoMapper.Mappers.MapperRegistry.Mappers);
var mappingEngine=new AutoMapper.mappingEngine(autoMapperCfg);
//用法示例
autoMapperCfg.CreateMap();
var b=映射引擎.Map(a);
(适用于2.2.1版)

//配置
var autoMapperCfg=new AutoMapper.ConfigurationStore(new AutoMapper.TypeMapFactory(),AutoMapper.Mappers.MapperRegistry.AllMappers());
var mappingEngine=new AutoMapper.mappingEngine(autoMapperCfg);
//用法示例
autoMapperCfg.CreateMap();
var b=映射引擎.Map(a);
@Omu:你和你的“ValueInjector”开始变得很烦人了。您不必使用ValueInjector插件(如果不是ValueInjector)回答每个AutoMapper问题。我个人对此很反感,因为你的策略,我甚至不想看它。这不是一个专业的人。
var config = new MapperConfiguration(cfg => {
    cfg.CreateMap<ClassA, ClassB>();
});

var mapper = config.CreateMapper();
// Configuration
AutoMapper.Mappers.MapperRegistry.Reset();
var autoMapperCfg = new AutoMapper.ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
var mappingEngine = new AutoMapper.MappingEngine(autoMapperCfg);
autoMapperCfg.Seal();

//Usage example
autoMapperCfg.CreateMap<ClassA, ClassB>();

var b = mappingEngine.Map<ClassB>(a);
// Configuration
var platformSpecificRegistry = AutoMapper.Internal.PlatformAdapter.Resolve<IPlatformSpecificMapperRegistry>();
platformSpecificRegistry.Initialize();

var autoMapperCfg = new AutoMapper.ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers);
var mappingEngine = new AutoMapper.MappingEngine(autoMapperCfg);

//Usage example
autoMapperCfg.CreateMap<ClassA, ClassB>();

var b = mappingEngine.Map<ClassB>(a);
// Configuration
var autoMapperCfg = new AutoMapper.ConfigurationStore(new AutoMapper.TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.AllMappers());
var mappingEngine = new AutoMapper.MappingEngine(autoMapperCfg);

//Usage example
autoMapperCfg.CreateMap<ClassA, ClassB>();

var b = mappingEngine.Map<ClassB>(a);