tutorial mvc initialize inicializar example createmap c# .net repository automapper

c# - mvc - mapper initialize



AutoMapper.Map ignora todas las propiedades de valor nulo del objeto fuente (5)

Estoy tratando de mapear 2 objetos del mismo tipo. Lo que quiero hacer es AutoMapper para ignorar todas las propiedades, que tienen un valor Null en el objeto de origen y mantener el valor existente en el objeto de destino.

He intentado usar esto en mi "Repositorio", pero no parece funcionar.

Mapper.CreateMap<TEntity, TEntity>().ForAllMembers(p => p.Condition(c => !c.IsSourceValueNull));

Cuál podría ser el problema ?


Hasta ahora lo he resuelto así.

foreach (var propertyName in entity.GetType().GetProperties().Where(p=>!p.PropertyType.IsGenericType).Select(p=>p.Name)) { var value = entity.GetType().GetProperty(propertyName).GetValue(entity, null); if (value != null) oldEntry.GetType().GetProperty(propertyName).SetValue(oldEntry, value, null); }

pero aún con la esperanza de encontrar una solución utilizando AutoMapper


Interesante, pero tu intento original debería ser el camino a seguir. La prueba de abajo es verde:

using AutoMapper; using NUnit.Framework; namespace Tests.UI { [TestFixture] class AutomapperTests { public class Person { public string FirstName { get; set; } public string LastName { get; set; } public int? Foo { get; set; } } [Test] public void TestNullIgnore() { Mapper.CreateMap<Person, Person>() .ForAllMembers(opt => opt.Condition(srs => !srs.IsSourceValueNull)); var sourcePerson = new Person { FirstName = "Bill", LastName = "Gates", Foo = null }; var destinationPerson = new Person { FirstName = "", LastName = "", Foo = 1 }; Mapper.Map(sourcePerson, destinationPerson); Assert.That(destinationPerson,Is.Not.Null); Assert.That(destinationPerson.Foo,Is.EqualTo(1)); } } }


Llevando la solución de Marty (que funciona) un paso más allá, aquí hay un método genérico para facilitar su uso:

public static U MapValidValues<U, T>(T source, U destination) { // Go through all fields of source, if a value is not null, overwrite value on destination field. foreach (var propertyName in source.GetType().GetProperties().Where(p => !p.PropertyType.IsGenericType).Select(p => p.Name)) { var value = source.GetType().GetProperty(propertyName).GetValue(source, null); if (value != null && (value.GetType() != typeof(DateTime) || (value.GetType() == typeof(DateTime) && (DateTime)value != DateTime.MinValue))) { destination.GetType().GetProperty(propertyName).SetValue(destination, value, null); } } return destination; }

Uso:

class Person { public string Name { get; set; } public int? Age { get; set; } public string Role { get; set; } } Person person = new Person() { Name = "John", Age = 21, Role = "Employee" }; Person updatePerson = new Person() { Role = "Manager" }; person = MapValidValues(updatePerson, person);


Work Around: agregar propiedad DataMember en el tipo de destino [DataMember (EmitDefaultValue = false)] eliminará la propiedad si el valor de origen es nulo.

[DataContract] class Person { [DataMember] public string Name { get; set; } [DataMember] public int? Age { get; set; } [DataMember(EmitDefaultValue = false)] public string Role { get; set; } }

si el valor del rol es nulo, se eliminará la propiedad del rol.


Condition sobrecarga de Condition con 3 parámetros le permite hacer una expresión equivalente a su ejemplo p.Condition(c => !c.IsSourceValueNull) :

Método de firma:

void Condition(Func<TSource, TDestination, TMember, bool> condition

Expresión equivalente:

CreateMap<TSource, TDestination>.ForAllMembers( opt => opt.Condition((src, dest, sourceMember) => sourceMember != null));