Automapper - 继承映射器在使用Construct时无法工作

3

昨天我发布了这篇文章:

Automapper - Inheritance mapper not working with type converter

现在我正在尝试按照@jimmy-bogard的答案所说做,但是不幸的是仍然没有成功。基类成员没有被映射。

Jimmy说:

然而,你可以使用ConstructUsing来构建初始目标对象。或者使用一个继承的自定义AfterMap。只是不能使用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?

如果您能提供帮助,将不胜感激。


你想要实现什么?让 Mapper.Map<Derived1>(source) 起作用吗? - Evk
是的!@Evk。所有基本属性都正确映射了。 - gabaros
你需要使用类型转换器吗?因为在你的例子中,你实际上并不需要它。 - Evk
是的! @Evk,我的例子非常基础,只是为了演示目的。实际上,我的映射比那更复杂。例如,我需要查找数据库中的某些属性值并相应地进行映射。 - gabaros
1个回答

2

你现在的做法不会奏效,因为在ConstructUsing中你创建了一个BaseClass的实例,然而当你将源映射到Derived1类时,你需要一个Derived1类的实例,而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方法更改为也返回派生类的实例,然后使用ConstructUsing,但不是在基类映射上,而是在Derived类映射上。


谢谢!你帮了我很多。然而,我不认为需要继承映射。我只是删除了基础映射,并将派生的映射保留下来,没有包含基础调用,一切都正常工作,因为基础映射实际上发生在派生映射中。 - gabaros
是的,我只是留下了这个,以防在实际情况中您使用 ForMember 部分映射基类属性,仅使用 Construct 映射复杂属性。否则,您不需要所有这些。 - Evk

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