Создайте две карты Automapper между теми же двумя типами объектов
Я использую AutoMapper в службе WCF для возврата объектов User
. User
имеет такие свойства, как AccountTeams
, который сам имеет дочерние объекты. Все классы имеют карты AutoMapper.
В зависимости от вызываемого WCF OperationContract
, я хочу вернуть разные объемы данных. Я хочу, чтобы один OperationContract
возвращал объект User
без его свойства AccountTeams
(и их дочерних элементов) и другого OperationContract
, чтобы вернуть User
всю заполненную цепочку свойств.
Есть ли способ иметь две разные карты между одними и теми же двумя объектами или мне нужно выполнить полное сопоставление и null
из свойств, которые я не хочу возвращать из службы?
Ответы
Ответ 1
Кевин Калитовски поднял хороший аргумент в отношении ответа wal: если нам нужны две конфигурации для обработки, которые должны быть разными, тогда нам не нужно дублировать все другие сопоставления, которые являются общими?
Я думаю, что нашел способ обойти это с помощью профилей: иметь один профиль для каждого из уникальных сопоставлений и третий профиль для общих сопоставлений. Затем создайте две конфигурации, по одному для каждого уникального профиля, а также добавьте общий профиль в каждую конфигурацию.
Пример, в AutoMapper 4.2:
Классы, которые должны отображаться: пользователь и транспортное средство:
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Vehicle
{
public int FleetNumber { get; set; }
public string Registration { get; set; }
}
Профили:
public class Profile1 : Profile
{
protected override void Configure()
{
base.CreateMap<User, User>();
}
}
public class Profile2 : Profile
{
protected override void Configure()
{
base.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
}
}
public class CommonProfile : Profile
{
protected override void Configure()
{
base.CreateMap<Vehicle, Vehicle>();
}
}
Затем создайте конфигурации и сопоставьте объекты:
[TestMethod]
public void TestMethod()
{
var user = new User() { Name = "John", Age = 42 };
var vehicle = new Vehicle {FleetNumber = 36, Registration = "XYZ123"};
var configuration1 = new MapperConfiguration(cfg =>
{
cfg.AddProfile<CommonProfile>();
cfg.AddProfile<Profile1>();
});
var mapper1 = configuration1.CreateMapper();
var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age
var mappedVehicle1 = mapper1.Map<Vehicle, Vehicle>(vehicle);//Maps both FleetNumber
//and Registration.
var configuration2 = new MapperConfiguration(cfg =>
{
cfg.AddProfile<CommonProfile>();
cfg.AddProfile<Profile2>();
});
var mapper2 = configuration2.CreateMapper();
var mappedUser2 = mapper2.Map<User, User>(user);//maps only Name
var mappedVehicle2 = mapper2.Map<Vehicle, Vehicle>(vehicle);//Same as mappedVehicle1.
}
Я пробовал это, и он работает.
Ответ 2
Я предполагаю, что вы выполняете сопоставление от User
до User
(если нет, то просто измените тип адресата)
Предположим, что этот класс для следующего примера:
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
Затем вы можете использовать отдельный AutoMapper.Configuration
, чтобы определить 2 карты:
[TestMethod]
public void TestMethod()
{
var configuration1 = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
var mapper1 = new MappingEngine(configuration1);
configuration1.CreateMap<User, User>();
var user = new User() { Name = "John", Age = 42 };
var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age
var configuration2 = new Configuration(new TypeMapFactory(), MapperRegistry.AllMappers());
configuration2.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
var mapper2 = new MappingEngine(configuration2);
var mappedUser2 = mapper2.Map<User, User>(user);
Assert.AreEqual(0, mappedUser2.Age);//maps only Name
}
Чтобы избежать сопоставления каждого другого типа дважды, вы можете добавить общий метод, который принимает Configuration
, который отображает все, что может быть достигнуто с User
, и вызывает это как на configuration1
, так и на configuration2
после вызовов CreateMap
.
Update
Для Automapper 4.x используйте следующее:
var configuration1 = new MapperConfiguration(cfg =>
{
cfg.CreateMap<User, User>();
});
var mapper1 = configuration1.CreateMapper();
var user = new User() { Name = "John", Age = 42 };
var mappedUser1 = mapper1.Map<User, User>(user);//maps both Name and Age
var configuration2 = new MapperConfiguration(cfg =>
{
cfg.CreateMap<User, User>().ForMember(dest => dest.Age, opt => opt.Ignore());
});
var mapper2 = configuration2.CreateMapper();
var mappedUser2 = mapper2.Map<User, User>(user); //maps only Name
Ответ 3
Я думаю, что вы можете решить эту проблему с помощью различных объектов Configuration, как описано здесь, вы можете найти пример этого здесь