忽略基类上的属性

本文关键字:属性 基类 | 更新日期: 2023-09-27 18:12:56

我很难忽略继承自基类的类的属性。

Mapper.CreateMap<FormViewModelBase, EntityBase>()
.Include<FormViewModel, Entity>()
.ForMember(x => x.Id, o => o.Ignore());
Mapper.CreateMap<FormViewModel, Entity>();
这里唯一需要注意的是,基类的属性是String,派生类的属性是Int32。

无论如何,当我尝试将FormViewModel的实例映射到Entity时,Entity类上基于字符串的Id属性总是被设置为来自FormViewModel的Int值,即使我已经指定忽略它。

我在FormViewModel和Entity上使用不同类型的Id的原因是,我在web应用程序中使用RavenDB,对象可以通过字符串或int Id加载。在客户端,Int Id是首选,因为标准的基于Raven字符串的Id在生成链接时不能很好地发挥作用。

谁能告诉我这里出了什么问题?

忽略基类上的属性

那么你的基类看起来像这样吗?

public class FormViewModelBase
{
   public string Id { get; set; }
   // other stuff
}

和你的派生类看起来像这样?

public class FormViewModel : FormViewModelBase
{
   public new int Id { get; set; }
   // other stuff
}

我想是这样的。

如果是这种情况,那么派生Id隐藏了基本Id属性。

无论如何,所以你是在传递FormViewModel的实际实例并从中制作Entity对象吗?

我看到这一行:

Mapper.CreateMap<FormViewModel, Entity>();

它告诉我"从我发送给你的FormViewModel对象中为我创建一个新的Entity对象,并执行默认的常规操作来完成此操作。"

所以当你调用像

这样的东西时
var anEntity = AutoMapper.Mapper.Map<FormViewModel, Entity>(aFormViewModel);

它会使用那个Map,而不是基对象的那个。因为衍生的FormViewModel

如果你做了这样的事情:

Mapper.CreateMap<FormViewModel, Entity>()
.ForMember(x => x.Id, o => o.Ignore());

来处理你的派生对象的映射,它会映射它,我猜,正如你想要的,但它可能有助于更多地了解你想要做的事情。

您需要在子类的映射中指定映射细节(比如忽略某些属性),而不是父类。例如:

Mapper.CreateMap<ParentA, ParentB>
      .Include<ChildA, ChildB>();
Mapper.CreateMap<ChildA, ChildB>
      .ForMember(dest => dest.SomeProperty, opt => opt.Ignore());

你的代码不工作的原因是你在父映射上指定了Ignore()。

我知道这个问题已经有一年了,但我还没有找到一个解决方案来回答这类问题。我也有同样的问题,经过一些挖掘,我发现唯一的事情是这种行为没有很好地记录。映射基类可以工作,但是由于某些原因忽略它们就不行。

我使用了这个扩展方法,它为我工作了

public static IMappingExpression<TSource, TDestination>
        InheritMappingFromBaseType<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
    {
        var sourceType = typeof(TSource);
        var desctinationType = typeof(TDestination);
        var sourceParentType = sourceType.BaseType;
        var destinationParentType = desctinationType.BaseType;
        expression
            .ForAllMembers(x => x.Condition(r => NotAlreadyMapped(sourceParentType, destinationParentType, r)));
        return expression;
    }
    private static bool NotAlreadyMapped(Type sourceType, Type desitnationType, ResolutionContext r)
    {
        return !r.IsSourceValueNull &&
               Mapper.FindTypeMapFor(sourceType, desitnationType).GetPropertyMaps().Where(
                   m => m.DestinationProperty.Name.Equals(r.MemberName)).Select(y => !y.IsMapped()).All(b => b);
    }

它是这样使用的(注意你需要在基类映射中使用ignore声明)

CreateMap<DerivedClassSource, DerivedClassDestination>()
            .InheritMappingFromBaseType()

它所做的是映射没有使用基类映射映射的任何属性。换句话说,它打破了默认的映射优先级。

我在这里找到了源代码并对其进行了一些修改,因为一些原始方法的代码现在在AutoMapper 2和3中实现了

在将此作为AutoMapper的问题提出后,没有使用Include添加Ignore的原因是没有办法取消忽略-映射仍然可以在基类中被覆盖。

当前实现此行为的唯一方法是用[IgnoreMap]属性装饰目标属性,但这可能与您的其余配置不一致,因此您需要决定它是否值得!