C# 在映射期间添加上下文

C# 在映射期间添加上下文,c#,automapper,C#,Automapper,我有一个类,它有一个Thing集合,可以通过Id和ThingCollectionId来识别 对应的DtoThing仅包含Id,我想在映射DtoThing到对象时,从全局已知的ThingCollections类加载PropertyNotInDto属性 // sources for mapping public class MyClass { public Guid ThingCollectionId {get;set;} public Dictionary<Thing, My

我有一个类,它有一个
Thing
集合,可以通过
Id
ThingCollectionId
来识别

对应的
DtoThing
仅包含
Id
,我想在映射
DtoThing
对象时,从全局已知的
ThingCollections
类加载
PropertyNotInDto
属性

// sources for mapping
public class MyClass {
    public Guid ThingCollectionId {get;set;}
    public Dictionary<Thing, MyClassB> Things {get;set;}
}
public class Thing {
    public int Id {get;set;}
    // other properties
    public string PropertyNotInDto {get;set;}
}
// targets for mapping
public class DtoMyClass {
    public Guid ThingCollectionId {get;set;}
    public Dictionary<DtoThing, DtoMyClassB> Things {get;set;}
}
public class DtoThing {
    public int Id {get;set;}
    // no other properties are saved in the DtoThing class
}
// global
public class ThingCollections {
    public Dictionary<Guid, List<Thing>> ThingCollections {get;}
}
这可以通过
DtoMyClass
MyClass
映射上的
IMappingAction
来实现,但这需要我重新构建事物列表,并将映射代码添加到
MyDtoClass
而不是
DtoThing

// sources for mapping
public class MyClass {
    public Guid ThingCollectionId {get;set;}
    public Dictionary<Thing, MyClassB> Things {get;set;}
}
public class Thing {
    public int Id {get;set;}
    // other properties
    public string PropertyNotInDto {get;set;}
}
// targets for mapping
public class DtoMyClass {
    public Guid ThingCollectionId {get;set;}
    public Dictionary<DtoThing, DtoMyClassB> Things {get;set;}
}
public class DtoThing {
    public int Id {get;set;}
    // no other properties are saved in the DtoThing class
}
// global
public class ThingCollections {
    public Dictionary<Guid, List<Thing>> ThingCollections {get;}
}
其中
ThingMappingAction
可以访问
ThingCollectionId

我目前的做法如下:

 CreateMap<DtoThing, Thing>().AdvancedMapping<ThingMappingAction>();
CreateMap<DtoMyClass, MyClass>().AfterMap<MyClassMappingAction>();
...
public MyClassMappingAction : IMappingAction<DtoMyClass, MyClass> {
    private ThingCollections ThingCollections {get;}
    public MyClassMappingAction(ThingCollections thingCollections){
       ThingCollections = thingCollections;
    }
    public void Process(MyDtoClass source, MyClass target) {
        // fix target.Things with ThingCollectionId, Thing.Id and ThingCollections
    }
}
CreateMap().AfterMap();
...
公共MyClassMappingAction:ImapingAction{
私有ThingCollections ThingCollections{get;}
公共MyClassMappingAction(ThingCollections ThingCollections){
ThingCollections=ThingCollections;
}
公共作废进程(MyDtoClass源、MyClass目标){
//使用ThingCollectionId、Thing.Id和ThingCollections修复target.Things
}
}

但这尤其令人恼火,因为
Thing
在多个属性中使用,并且每个这样的实例都需要特殊的代码,这需要添加到
MyClassMappingAction

我通过在
BeforeMap
的上下文中添加
ThingCollectionId
并使用
itypecoverter
再次访问它来实现

CreateMap<DtoMyClass, MyClass>().BeforeMap((dto, myclass, context) => context.Items["ThingCollectionId"] = dto.ThingCollectionId);
CreateMap<DtoThing, Thing>().ConvertUsing<ThingTypeConverter>();

public ThingTypeConverter: ITypeConverter<DtoThing, Thing> {
    private ThingCollections ThingCollections {get;}
    public MyClassMappingAction(ThingCollections thingCollections){
       ThingCollections = thingCollections;
    }
    public Thing Convert(DtoThing source, Thing destination, ResolutionContext context) {
        // Get the correct ThingCollection by ThingCollectionId
        var thingCollection = ThingCollections[(Guid)context.Items["ThingCollectionId"]];
        // Get the correct Thing from the ThingCollection by its Id
        return thingCollection.First(t => t.Id == source.Id);
    }
}
CreateMap().BeforeMap((dto,myclass,context)=>context.Items[“ThingCollectionId”]=dto.ThingCollectionId);
CreateMap().ConvertUsing();
公共ThingTypeConverter:ITypeConverter{
私有ThingCollections ThingCollections{get;}
公共MyClassMappingAction(ThingCollections ThingCollections){
ThingCollections=ThingCollections;
}
公共事物转换(数据源、事物目标、ResolutionContext上下文){
//通过ThingCollectionId获取正确的ThingCollection
var thingCollection=ThingCollections[(Guid)context.Items[“ThingCollectionId”];
//通过其Id从ThingCollection获取正确的内容
返回thingCollection.First(t=>t.Id==source.Id);
}
}

这将替换以前使用的
AfterMap
调用和
MyClassMappingAction
。这样一来,
Things
的映射代码a就不包含在
MyClass
的映射中,也就不需要再手动重新创建
MyClass.Things
字典了。

请尝试而不是AfterMap。@LucianBargaoanu感谢您的建议!我仍在想如何在映射配置文件中设置该上下文,而不是在调用
Mapper.Map
时设置该上下文。该上下文用于Map调用。对于其他情况,您可以使用DI,或者在映射配置文件中构造解析器实例时只传递值。