User
オブジェクトを返すために、WCFサービスでAutoMapperを使用しています。 User
には、それ自体が子オブジェクトを持つAccountTeams
などのプロパティがあります。すべてのクラスにはAutoMapperマップがあります。
呼び出されるWCF OperationContract
に応じて、さまざまな量のデータを返します。 OperationContract
プロパティ(およびその子)が設定されていないUser
オブジェクトを返すAccountTeams
と、プロパティのチェーン全体が埋められたOperationContract
を返す別のUser
が必要です。
同じ2つのオブジェクト間に2つの異なるマップを作成する方法はありますか、または完全なマッピングを実行し、サービスから返さないプロパティをnull
アウトする必要がありますか?
Kevin Kalitowskiはwalの答えについて良い点を挙げました。異なる必要があるマッピングを処理するために2つの構成が必要な場合、一般的な他のすべてのマッピングを複製する必要はありませんか?
プロファイルを使用してこれを回避する方法を見つけたと思います。一意のマッピングごとに1つのプロファイルを持ち、共通のマッピングのために3番目のプロファイルを持ちます。次に、一意のプロファイルごとに1つずつ、2つの構成を作成しますが、各構成にも共通のプロファイルを追加します。
例、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.
}
私はこれを試してみましたが、うまくいきます。
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
}
他のTypeを2回マッピングしないようにするには、Configuration
から到達可能なすべてをマッピングするUser
を取る共通メソッドを追加し、CreateMap
の呼び出し後にconfiguration1
とconfiguration2
の両方でこれを呼び出します。
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