Automapper - 继承映射器不适用于 Construct
Automapper - Inheritance mapper not working with Construct
就在昨天我发布了这个:
现在我正在尝试按照@jimmy-bogard 在他的回答中所说的去做,但不幸的是仍然没有成功。基本成员未映射。
吉米说:
However, you CAN use ConstructUsing to build out the initial
destination object. Or a custom AfterMap, that's also inherited. Just
not ConvertUsing.
这是我的新代码。
/* BaseClassConstructor.cs */
public class BaseClassConstructor {
public static BaseClass Construct(ResolutionContext context) {
if (context == null || context.IsSourceValueNull)
return null;
var src = (SourceClass)context.SourceValue;
return new BaseClass() {
CommonAttr = src.SourceAttr
};
}
}
/* AutoMapperConfig.cs */
public static class AutoMapperConfig {
public static void RegisterMappings() {
AutoMapper.Mapper.Initialize(config => {
config
.CreateMap<SourceClass, BaseClass>()
.Include<SourceClass, DerivedClass1>()
.Include<SourceClass, DerivedClass2>()
.ConstructUsing(s => BaseClassConstructor.Construct(s));
config
.CreateMap<SourceClass, DerivedClass1>()
.ForMember(dest => dest.Dummy, o => o.MapFrom(src => src.SourceAttr2))
.IncludeBase<SourceClass, BaseClass>();
});
}
}
我错过了什么吗?
我使用 ConstructUsing 的方式是否正确?
如有任何帮助,我们将不胜感激。
你现在的方式行不通,因为在 ConstructUsing
中你创建了一个 BaseClass
的实例,而当你将源映射到 Derived1
class - 您需要 Derived1
class 的实例,并且 BaseClass
无法转换为该实例(向下转换)。但是你可以这样做:
public class BaseClassConstructor {
public static T Construct<T>(ResolutionContext context) where T : BaseClass, new() {
if (context == null || context.IsSourceValueNull)
return null;
var src = (SourceClass) context.SourceValue;
return new T() {
CommonAttr = src.SourceAttr
};
}
}
/* AutoMapperConfig.cs */
public static class AutoMapperConfig
{
public static void RegisterMappings()
{
AutoMapper.Mapper.Initialize(config => {
config
.CreateMap<SourceClass, BaseClass>();
config
.CreateMap<SourceClass, DerivedClass1>()
.ForMember(dest => dest.Dummy, o => o.MapFrom(src => src.SourceAttr2))
.IncludeBase<SourceClass, BaseClass>()
.ConstructUsing((s, ctx) => BaseClassConstructor.Construct<DerivedClass1>(ctx));
config
.CreateMap<SourceClass, DerivedClass2>()
.ForMember(dest => dest.Dummy, o => o.MapFrom(src => src.SourceAttr2))
.IncludeBase<SourceClass, BaseClass>()
.ConstructUsing((s, ctx) => BaseClassConstructor.Construct<DerivedClass2>(ctx));
});
}
}
基本上我也将您的 Construct
方法更改为派生 class 的 return 个实例,然后使用 ConstructUsing
,但不是基于 class映射但在 Derived
classes 映射上。
就在昨天我发布了这个:
现在我正在尝试按照@jimmy-bogard 在他的回答中所说的去做,但不幸的是仍然没有成功。基本成员未映射。
吉米说:
However, you CAN use ConstructUsing to build out the initial destination object. Or a custom AfterMap, that's also inherited. Just not ConvertUsing.
这是我的新代码。
/* BaseClassConstructor.cs */
public class BaseClassConstructor {
public static BaseClass Construct(ResolutionContext context) {
if (context == null || context.IsSourceValueNull)
return null;
var src = (SourceClass)context.SourceValue;
return new BaseClass() {
CommonAttr = src.SourceAttr
};
}
}
/* AutoMapperConfig.cs */
public static class AutoMapperConfig {
public static void RegisterMappings() {
AutoMapper.Mapper.Initialize(config => {
config
.CreateMap<SourceClass, BaseClass>()
.Include<SourceClass, DerivedClass1>()
.Include<SourceClass, DerivedClass2>()
.ConstructUsing(s => BaseClassConstructor.Construct(s));
config
.CreateMap<SourceClass, DerivedClass1>()
.ForMember(dest => dest.Dummy, o => o.MapFrom(src => src.SourceAttr2))
.IncludeBase<SourceClass, BaseClass>();
});
}
}
我错过了什么吗? 我使用 ConstructUsing 的方式是否正确?
如有任何帮助,我们将不胜感激。
你现在的方式行不通,因为在 ConstructUsing
中你创建了一个 BaseClass
的实例,而当你将源映射到 Derived1
class - 您需要 Derived1
class 的实例,并且 BaseClass
无法转换为该实例(向下转换)。但是你可以这样做:
public class BaseClassConstructor {
public static T Construct<T>(ResolutionContext context) where T : BaseClass, new() {
if (context == null || context.IsSourceValueNull)
return null;
var src = (SourceClass) context.SourceValue;
return new T() {
CommonAttr = src.SourceAttr
};
}
}
/* AutoMapperConfig.cs */
public static class AutoMapperConfig
{
public static void RegisterMappings()
{
AutoMapper.Mapper.Initialize(config => {
config
.CreateMap<SourceClass, BaseClass>();
config
.CreateMap<SourceClass, DerivedClass1>()
.ForMember(dest => dest.Dummy, o => o.MapFrom(src => src.SourceAttr2))
.IncludeBase<SourceClass, BaseClass>()
.ConstructUsing((s, ctx) => BaseClassConstructor.Construct<DerivedClass1>(ctx));
config
.CreateMap<SourceClass, DerivedClass2>()
.ForMember(dest => dest.Dummy, o => o.MapFrom(src => src.SourceAttr2))
.IncludeBase<SourceClass, BaseClass>()
.ConstructUsing((s, ctx) => BaseClassConstructor.Construct<DerivedClass2>(ctx));
});
}
}
基本上我也将您的 Construct
方法更改为派生 class 的 return 个实例,然后使用 ConstructUsing
,但不是基于 class映射但在 Derived
classes 映射上。