2012-07-10 19 views

risposta

7

Non ho trovato il modo migliore rispetto al seguente.

Qui sono la fonte e la destinazione.

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

Definire convertitore (Si dovrebbe cambiare Lista <> a qualsiasi tipo che si sta utilizzando).

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

E qui è la configurazione di mappatura effettiva ed esempio.

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

Si dovrebbe ottenere il seguente risultato.

Mapping result

1

Ho trovato questo articolo molto utile e come tale ho pensato di feed back nella mia versione generica del convertitore tipo che è possibile utilizzare per selezionare la proprietà in modo che corrisponda a da ogni oggetto.

Con esso tutto quello che dovete fare è:

// 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; 
    } 
} 
Problemi correlati