2012-07-10 7 views

Respuesta

7

no he encontrado mejor manera que la siguiente.

Éstos son origen y destino.

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; } 
} 

Definir convertidor (Debe cambiar Lista <> a cualquier tipo que esté utilizando).

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; 
    } 
} 

Y aquí está la configuración de asignación real y el ejemplo.

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); 

Debe obtener el siguiente resultado.

Mapping result

1

He encontrado este artículo muy útil y, como tal, pensé que iba a alimentar de nuevo en mi versión genérica del convertidor de tipos que se puede utilizar para seleccionar la propiedad para que coincida con el de cada objeto.

Utilizando todo lo que necesita hacer es:

// 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; 
    } 
} 
Cuestiones relacionadas