【问题标题】:Map list to existing list in Automapper using a key使用键将列表映射到 Automapper 中的现有列表
【发布时间】:2012-07-09 22:12:48
【问题描述】:

Automapper 可以轻松处理将一个对象类型列表映射到另一个不同对象类型列表,但是是否可以使用 ID 作为键将其映射到现有列表?

【问题讨论】:

    标签: c# automapper automapper-2


    【解决方案1】:

    我发现这篇文章非常有用,因此我想我会在我的类型转换器的通用版本中进行反馈,您可以使用它来从每个对象中选择要匹配的属性。

    使用它你需要做的就是:

    // Example of usage
    Mapper.CreateMap<UserModel, User>();
    var converter = CollectionConverterWithIdentityMatching<UserModel, User>.Instance(model => model.Id, user => user.Id);
    Mapper.CreateMap<List<UserModel>, List<User>>().ConvertUsing(converter);
    
    //The actual converter
    public class CollectionConverterWithIdentityMatching<TSource, TDestination> : 
        ITypeConverter<List<TSource>, List<TDestination>> where TDestination : class
    {
        private readonly Func<TSource, object> sourcePrimaryKeyExpression;
        private readonly Func<TDestination, object> destinationPrimaryKeyExpression;
    
        private CollectionConverterWithIdentityMatching(Expression<Func<TSource, object>> sourcePrimaryKey, Expression<Func<TDestination, object>> destinationPrimaryKey)
        {
            this.sourcePrimaryKeyExpression = sourcePrimaryKey.Compile();
            this.destinationPrimaryKeyExpression = destinationPrimaryKey.Compile();
        }
    
        public static CollectionConverterWithIdentityMatching<TSource, TDestination> 
            Instance(Expression<Func<TSource, object>> sourcePrimaryKey, Expression<Func<TDestination, object>> destinationPrimaryKey)
        {
            return new CollectionConverterWithIdentityMatching<TSource, TDestination>(
                sourcePrimaryKey, destinationPrimaryKey);
        }
    
        public List<TDestination> Convert(ResolutionContext context)
        {
            var destinationCollection = (List<TDestination>)context.DestinationValue ?? new List<TDestination>();
            var sourceCollection = (List<TSource>)context.SourceValue;
            foreach (var source in sourceCollection)
            {
                TDestination matchedDestination = default(TDestination);
    
                foreach (var destination in destinationCollection)
                {
                    var sourcePrimaryKey = GetPrimaryKey(source, this.sourcePrimaryKeyExpression);
                    var destinationPrimaryKey = GetPrimaryKey(destination, this.destinationPrimaryKeyExpression);
    
                    if (string.Equals(sourcePrimaryKey, destinationPrimaryKey, StringComparison.OrdinalIgnoreCase))
                    {
                        Mapper.Map(source, destination);
                        matchedDestination = destination;
                        break;
                    }
                }
    
                if (matchedDestination == null)
                {
                    destinationCollection.Add(Mapper.Map<TDestination>(source));
                }
            }
    
            return destinationCollection;
        }
    
        private string GetPrimaryKey<TObject>(object entity, Func<TObject, object> expression)
        {
            var tempId = expression.Invoke((TObject)entity);
            var id = System.Convert.ToString(tempId);
            return id;
        }
    }
    

    【讨论】:

      【解决方案2】:

      我没有找到比以下更好的方法。

      这里是来源和目的地。

      public class Source
      {
          public int Id { get; set; } 
          public string Foo { get; set; }
      }
      
      public class Destination 
      { 
          public int Id { get; set; }
          public string Foo { get; set; }
      }
      

      定义转换器(您应该将 List 更改为您正在使用的任何类型)。

      public class CollectionConverter: ITypeConverter<List<Source>, List<Destination>>
      {
          public List<Destination> Convert(ResolutionContext context)
          {
              var destinationCollection = (List<Destination>)context.DestinationValue;
              if(destinationCollection == null)
                  destinationCollection = new List<Destination>();
              var sourceCollection = (List<Source>)context.SourceValue;
              foreach(var source in sourceCollection)
              {
                  Destination matchedDestination = null;
      
                  foreach(var destination in destinationCollection)
                  {
                      if(destination.Id == source.Id)
                      {
                          Mapper.Map(source, destination);
                          matchedDestination = destination;
                          break;
                      }
                  }
                  if(matchedDestination == null)
                      destinationCollection.Add(Mapper.Map<Destination>(source));
              }
              return destinationCollection;
          }
      }
      

      这是实际的映射配置和示例。

      Mapper.CreateMap<Source,Destination>();
      Mapper.CreateMap<List<Source>,List<Destination>>().ConvertUsing(new CollectionConverter());
      
      var sourceCollection = new List<Source>
      {
          new Source{ Id = 1, Foo = "Match"},
          new Source{ Id = 2, Foo = "DoesNotMatchWithDestination"}
      };
      var destinationCollection = new List<Destination>
      {
          new Destination{ Id = 1, Foo = "Match"},
          new Destination{ Id = 3, Foo = "DoeNotMatchWithSource"}
      };
      var mergedCollection = Mapper.Map(sourceCollection, destinationCollection);
      

      你应该得到以下结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-05-09
        • 2011-08-01
        • 2018-03-19
        • 2016-10-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多