AutoMapper 字典到类 - 如何忽略不支持的属性映射?

问题描述 投票:0回答:1

我想将 Dictionary 类型的动态对象转换为类型化类。 Automapper 默认情况下允许这样做,无需创建显式地图:

https://docs.automapper.org/en/stable/Dynamic-and-ExpandoObject-Mapping.html

Automapper 遍历字典中的键,当目标类中的属性名称匹配时,它会尝试设置该属性。然而,当转换失败时它会抛出异常。

有没有办法将映射器设置为仅映射源字典中可转换的项目并忽略无法转换的项目?在下面的示例中,类型 Sample1 的实例结果已正确填充。

public class Sample1
{
    public string str_number { get; set; }
    public string description { get; set; }
    public DateTime date_from { get; set; }
}

var dynamicItems = new Dictionary<string, object> {
    ["str_number"] = 123456,
    ["description"] = "lorem ipsum",
    ["date_from"] = "2023-11-27"
};

var mapperConf = new MapperConfiguration(cfg => {});
var mapper = new Mapper(mapperConf);
var result = mapper.Map<Sample1>(dynamicItems);

但是如果我改变,例如[“date_from”] 到字典中的值“2023-11-27xxx”,然后 Automapper 抛出异常。我想获得属性 date_from 未设置(默认值)的结果。

编辑:

我通过使用 NewtonSoft 包的 JSON 序列化找到了一个解决方案。 JsonSerializerSettings 中的错误处理程序执行的技巧是仅设置可转换属性,其他属性保留默认值。

private static T Convert<T>(IDictionary<string, object> cmProperties) where T : class, new()
{
    // ignore properties that could not be converted to destination type
    var settings = new JsonSerializerSettings
    {
        Error = (_, eventArgs) =>
        {
            eventArgs.ErrorContext.Handled = true;
        }
    };

    // serialize dictionary to JSON
    var json = JsonConvert.SerializeObject(cmProperties);

    // deserialize JSON to typed class or return new empty instance
    return JsonConvert.DeserializeObject<T>(json, settings) ?? new T();
}
c# automapper
1个回答
0
投票

如果您的日期时间字符串可能很笨拙并且必须进行清理,则必须定义从 stringDateTime 的特定转换器。这可以通过配置文件来完成,最简单(目前失败)的方法是:

public class MyProfile : Profile
{
    public MyProfile()
    {
        CreateMap<string, DateTime>()
            .ConvertUsing(source => DateTime.Parse(source));
    }
}

必须将其添加到您的配置中:

var mapperConf = new MapperConfiguration(cfg => { cfg.AddProfile<MyProfile>(); });
var mapper = new Mapper(mapperConf);
var result = mapper.Map<Sample1>(dynamicItems);

虽然这仍然像原始代码一样失败,但您现在有了一个可以执行某些操作的入口点。为了避免给定的示例带有一些无效的后缀,您可以在解析之前缩短字符串:

CreateMap<string, DateTime>()
    .ConvertUsing(source => DateTime.Parse(source.Substring(0, 10)));

如果从给定字符串中提取所需日期时间信息的逻辑更复杂并且不适合简单的 lambda,您可以提供相应的转换器并执行所需的操作将给定字符串转换为有意义的日期时间对象:

public class StringDateTimeConverter : ITypeConverter<string, DateTime>
{
    public DateTime Convert(string source, DateTime destination, ResolutionContext context)
    {
        return DateTime.TryParse(source[..10], out DateTime result)
            ? result
            : DateTime.UtcNow;
    }
}

public class MyProfile : Profile
{
    public MyProfile()
    {
        CreateMap<string, DateTime>()
            .ConvertUsing<StringDateTimeConverter>();
    }
}

如果您的映射失败或者您返回占位符文件夹或近似值,则由您决定。只需将您的期望实现到转换器的 Convert() 方法中,它就会执行您想要的操作。

© www.soinside.com 2019 - 2024. All rights reserved.