【问题标题】:Strict type validation of properties in AutomapperAutomapper 中属性的严格类型验证
【发布时间】:2019-01-10 13:35:31
【问题描述】:

是否可以设置某种全局配置,当映射对象的某些属性具有相同名称但具有不同类型时,会导致映射或验证过程失败?

来源/目的地类型

public class UserData1
{
    public int Id { get; set; }
}

public class UserData2
{
    public string Id { get; set; }
}

映射配置

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<UserData1, UserData2>();
});

预期行为

当映射属性的类型不同时,AssertConfigurationIsValid 或 Map 应该触发某种验证异常。

实际行为

int 属性无一例外地映射到字符串。

复制步骤

// Passes OK
 Mapper.Configuration.AssertConfigurationIsValid();

 // Mapping is successful
 var user2 = Mapper.Map<UserData2>(new UserData1 { Id = 156 });

【问题讨论】:

  • 您能否包含完整的示例而不是链接。链接将来可能无法使用。
  • 您可以通过扩展点添加自定义验证。见here
  • 从已关闭的 git 问题中添加了示例。
  • @LucianBargaoanu - 我最初的想法是使用自定义验证器,但它似乎会有更复杂的代码
  • 嗯,我不知道。它与验证干净地集成在一起。它有什么复杂之处?

标签: c# .net serialization automapper


【解决方案1】:

没有可用的内置解决方案,但可以使用自定义配置来实现。

类似这样的:

Mapper.Initialize(cfg => {
    cfg.CreateMap<UserData1, UserData2>();
    ...
    cfg.ForAllMaps((typeMap, mappingExpr) =>
    {
        foreach (var map in typeMap.PropertyMaps) {
            var sourcePropInfo = map.SourceMember as PropertyInfo;
            var destPropInfo = map.DestinationMember as PropertyInfo;

            if (sourcePropInfo == null || destPropInfo == null) continue;

            if (sourcePropInfo.PropertyType != destPropInfo.PropertyType)
                throw new Exception("Wrong property type!");
        }
    });
});

作为参考使用了这个旧帖子并更新以使用新版本的自动映射器 https://stackoverflow.com/a/38080647/1703620

【讨论】:

  • 谢谢。明天会检查这个。
【解决方案2】:

以 Artyom 的回答为灵感,我编写了一个单元测试来将这些隐式类型转换限制在我们可以接受的少数场景中。

方法是查找所有没有显式映射的属性映射,并过滤掉我们想要允许的少数场景。

XUnit 测试:

        [Fact]
        public void AllMappedPropertiesAreSameTypeOrAreMappedExplicitly()
        {
            ServiceCollection theCollection = new ServiceCollection();

            theCollection.AddMssAutoMapper();

            IMapper theMapper = BuildProductionMapper();

            //Store all explicit mappings for easy lookup
            System.Collections.Generic.HashSet<(Type SourceType, Type DestType)> theExplicitMappings =
                theMapper.ConfigurationProvider.GetAllTypeMaps()
                .Select( map => (map.SourceType, map.DestinationType) )
                .ToHashSet();

            var theIllegalMaps =
            from typeMap in theMapper.ConfigurationProvider.GetAllTypeMaps()
            from propMap in typeMap.PropertyMaps
            let sourceType = propMap.SourceType
            let destType = propMap.DestinationType
            let bothTypes = new[] { sourceType, destType }
            where sourceType != null && destType != null
            where sourceType != destType

            //Anything that's explicitly mapped is permitted
            where !theExplicitMappings.Contains( (sourceType, destType) )

            //enums to string and vice versa is permitted
            where !( sourceType.IsEnum || sourceType == typeof( string ) && destType.IsEnum || destType == typeof( string ) )

            //mapping from one collection to another is okay
            where !bothTypes.All( type => type.IsAssignableTo( typeof( IEnumerable ) ) )
            select new
            {
                SourceType = typeMap.SourceType,
                DestinationType = typeMap.DestinationType,
                SourceMemberName = propMap.SourceMember.Name,
                DestMemberName = propMap.DestinationMember.Name,
                SourceMemberType = sourceType,
                DestinationMemberType = destType
            };
            var illegalMapsList = theIllegalMaps.ToList();
            foreach( var illegalMap in illegalMapsList )
            {
                Console.Out.WriteLine( $"Found disallowed property mapping from '{illegalMap.SourceType}.{illegalMap.SourceMemberName}' to '{illegalMap.DestinationType}.{illegalMap.DestMemberName}'" );
                Console.Out.WriteLine( $"Property name: {illegalMap.SourceMemberName}" );
                Console.Out.WriteLine( $"implicit mapping from {illegalMap.SourceMemberType} to {illegalMap.DestinationMemberType} is not allowed." );
                Console.Out.WriteLine( $"Please map these types explicitly." );
            }

            if( illegalMapsList.Any() )
            {
                throw new Exception( "One or more ambiguous mappings were found that need to be handled explicitly.  See console output for details." );
            }
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多