首页 > 解决方案 > AutoMapper ForAllMaps 覆盖自定义设置

问题描述

在以下示例中(可在 LinqPad 中执行),MyString 变为“Hello World”。

但是,如果我取消注释 cfg.ForAllMaps 那么它只是“你好”,它显然会覆盖任何自定义设置。

我希望使用 cfg.ForAllMaps 来设置一堆通用规则,例如源上存在的一个属性,其名称与目标完全不同,但遵循一个通用模式,即源 DTO 中的 Person_Age,将匹配上的 Age 属性一个名为 Person 和 Animal_Age 的目标类型与 Animal.Age 等匹配。除此之外,Person 类型可能具有我希望执行的特定自定义。

ForAllMaps 是否意味着覆盖所有其他设置?如果是这样,是否可以以我希望的方式使用它,即具有可以覆盖的基线配置?或者是否有我应该使用的替代 API(我一直在四处寻找,但到目前为止没有发现任何东西)?

void Main()
{
    var config = new MapperConfiguration(cfg =>
    {
        //Uncomment this and ForCtorParam override does not work
//      cfg.ForAllMaps((typeMap, map) =>
//      {
//      });

        cfg.CreateMap<Source, Destination>()
            .ForCtorParam("myString", x => x.MapFrom(y => $"{y.MyString} World"));
    });

    config.AssertConfigurationIsValid();

    var mapper = config.CreateMapper();

    var source = new Source()
    {
        MyString = "Hello"
    };

    var dest = mapper.Map<Destination>(source);

    dest.Dump();
}

public class Source 
{
    public string MyString { get; set; }
}

public class Destination 
{
    public string MyString {get; private set;}

    public Destination(string myString)
    {
        this.MyString = myString;
    }
}

更多信息:

顺便说一句,这是我在 ForAllMaps 中执行的那种功能:

void SetupMemberAndRenamedContructorParameter<T>(TypeMap typeMap, IMappingExpression map, string sourcePropertyName, string destinationPropertyName, string destinationContructorParamaterName)
{
    map.ForMember(destinationPropertyName, x => x.MapFrom(sourcePropertyName));

    var propertyInfo = (PropertyInfo)typeMap.SourceTypeDetails.PublicReadAccessors.Single(w => w.Name == sourcePropertyName);

    Expression<Func<object, T>> getValue = (sourceClassInstance) => (T)propertyInfo.GetValue(sourceClassInstance);

    map.ForCtorParam(destinationContructorParamaterName, x => x.MapFrom(getValue));
}

cfg.ForAllMaps((typeMap, map) =>
{
    SetupMemberAndRenamedContructorParameter<string>(typeMap, map, $"{typeMap.DestinationType.Name.ToUpper()}_ERROR", "ErrorCode", "errorCode");
    SetupMemberAndRenamedContructorParameter<int>(typeMap, map, $"{typeMap.DestinationType.Name.ToUpper()}_RATING", "Flag", "flag");
});

为了澄清我的主要问题是关于 ForAllMaps 是否覆盖 CreateMap() 以及是否有办法让两者很好地协同工作,我的次要示例可能会分散注意力。

标签: c#automapperautomapper-9

解决方案


推荐阅读