【问题标题】:Automapper ValueTransformers from dynamic to a classAutomapper ValueTransformers 从动态到类
【发布时间】:2019-07-30 19:46:14
【问题描述】:

我的项目正在使用 AutoMapper 将动态对象转换为具体的类对象。每个具体类都有多个我想由 AutoMapper 修剪的字符串属性。有几十个这样的具体类,为每个映射设置一个 CustomTypeConverter 很乏味。我希望通过 ValueConverter 来实现这一点,如下所示:

这是我的映射器配置:

Mapper.Initialize(config =>
{
  config.ValueTransformers.Add<string>(val => val.Trim());
});

这是我的 DTO 之一:

public class MyDto
{
  public string MyProperty { get; set; }
}

这是我从动态映射到 MyDto 的方法:

public async Task<object> MyMethod(dynamic input)
{
  MyDto dto = Mapper.Map<MyDto>(input);
  // expect dto.MyProperty to be trimmed here, but it is not.
  // do work
}

我对 ValueTransformers 的基本理解是否不正确?我是否已为我正在映射的每个 DTO 显式添加一个 CustomTypeConverter 并为我需要修剪的每个属性使用 ForMember?

【问题讨论】:

  • 您可以创建一个从字符串到字符串的映射。
  • @LucianBargaoanu - 我也尝试过,但没有成功。

标签: c# automapper


【解决方案1】:

会不会是在被映射的那一刻,该属性的类型还不是字符串(因为是动态的)?不过不知道怎么测试,也许你可以用普通的类做一个快速测试。

如果是这种情况,您可以在 AfterMap 中使用一些反射来循环遍历所有字符串属性并修剪它们。

类似这样(这是将日期设置为 UTC 的示例,但您可以调整它):

    public static class DateKindHelper
    {
        /// <summary>
        /// Scans an object for all its properties, and sets the kind of DateTime and DateTime? ones to UTC.
        /// </summary>
        /// <param name="target">Any object, preferably POCO ones.</param>
        public static void SetAllDateTimeValuesAsUtc(object target)
        {
            if (target == null) return;

            // TODO: We could add a propertyInfo list cache in a static dictionary for each type, so it's faster.

            //Extract all DateTime properties of the object type
            var properties = target.GetType().GetProperties()
                .Where(property => property.PropertyType == typeof(DateTime) ||
                                   property.PropertyType == typeof(DateTime?)).ToList();
            //Set all DaetTimeKinds to Utc
            properties.ForEach(property => SpecifyUtcKind(property, target));
        }

        private static void SpecifyUtcKind(PropertyInfo property, object value)
        {
            // If the property doesn't have a setter, we don nothing!
            if (property.SetMethod == null) return;

            //Get the datetime value
            var datetime = property.GetValue(value, null);

            //set DateTimeKind to Utc
            if (property.PropertyType == typeof(DateTime))
            {
                datetime = DateTime.SpecifyKind((DateTime)datetime, DateTimeKind.Utc);
            }
            else if (property.PropertyType == typeof(DateTime?))
            {
                var nullable = (DateTime?)datetime;
                if (!nullable.HasValue) return;
                datetime = (DateTime?)DateTime.SpecifyKind(nullable.Value, DateTimeKind.Utc);
            }
            else
            {
                return;
            }

            //And set the Utc DateTime value
            property.SetValue(value, datetime, null);
        }
    }

【讨论】:

  • 这违背了 AM 的目的。
  • @LucianBargaoanu - 在这一点上,我已经完全放弃了自动映射器解决方案,所以我认为这个答案一点也不离谱。
  • 我只能说这是非常简单的东西。在这一点上,解决方案是众所周知的。但很明显,您永远不应该使用您不了解的技术。所以无论什么适合你。
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2018-09-01
  • 2018-08-07
  • 1970-01-01
相关资源
最近更新 更多