C#のジェネリックに基づくオブジェクトをオブジェクトmapper質問
質問
私のオブジェクトをオブジェクトmapper私の願います。私たながんでもう私のご要望にお応えできるように書いしました。現在、私はインターフェースは以下のように:
public interface IMapper<T, R> {
T Map(R obj);
}
その後、実施AccountMapperットをお客様のアカウントとして:
public class AccountMapper : IMapper<Account, Customer> {
Account Map(Customer obj) {
// mapping code
}
}
この作品は細かなしい複数のソース体地図の団体をいう。例えば私の支払いや請求書と地図をBillHistory.上記のことながらプレーする必要がありましては別mappersります。BillHistoryPaymentMapperとBillHistoryInvoiceMapper)である。しかし、プレイしていただければと思いきそして、それを実践するにはちょっと違う方法についてのものです。唯一の問題はどうか分かりませんので、その場合、わからない、正しい構文です。
public interface IMapper<T> {
T Map<R>(R obj);
}
public class BillHistoryMapper : IMapper<Account> {
public BillHistory Map<Invoice>(Invoice obj) {
// mapping code
}
public BillHistory Map<Payment>(Payment obj) {
// mapping code
}
}
最初の実施、第二が若干があります。こんなことが可能なので、その場合どのように正しい構文はどうなっているか。
編集-------
そんなの、そんな人がいろいろ忘れてしまったのもさすがに調度品等は古くなった。また抽象クラスとのマッパーのインターフェースを実装は、共通した理論の全てのmappers.このような中、私mapperの署名は:
public class BillHistoryMapper : Mapper<BillHistory, Invoice> {
}
がMapperを含む:
public abstract class Mapper<T, R> : IMapper<T, R> {
public IList<T> Map(IList<R> objList) {
return objList.ToList<R>().ConvertAll<T>(new Converter<T, R>(Map));
}
}
解決
あなたは、あなたのオブジェクト上で複数回、あなたの最初のインターフェイスを使用して、インターフェイスを実装する必要があります:
public class BillHistoryMapper : IMapper<Account, Invoice>,
IMapper<Account, Payment> {
...
}
私は深刻 AutoMapper に見てみるの代わりに、あなた自身を書いて検討します。それはすでに解決していることをマッピングでニュアンスがたくさんありますが、それはパフォーマンステスト、バグ修正などのたくさんをしてきたことは言うまでもありません。
他のヒント
お客様につきましてはabstractクラスに考えることが出来るのだろうかすことはでき延長方法。この利用できるようになりますの MapAll
機能の有無にかかわらず実装のインタフェースまたは使用に何らかの継承。
public static class MapperExtensions
{
public static IEnumerable<TOutput> MapAll<TInput, TOutput>
(this IMapper<TInput, TOutput> mapper, IEnumerable<TInput> input)
{
return input.Select(x => mapper.Map(x));
}
}
こうくしようとした場合に解決問題がなくなってからの継承を基底クラスでは、今までの実施のマッピングを行うためのインタフェースの種類にしたい。
public class BillHistoryMapper :
IMapper<Invoice, BillHistory>, IMapper<Payment, BillHistory>
{
public BillHistory Map<Invoice>(Invoice obj) {}
public BillHistory Map<Payment>(Payment obj) {}
}
また変更をご検討 IMapper
汎用パラメータを、それが逆になっているので(した理由は、前の例):
public interface IMapper<in TInput, out TOutput>
{
TOutput Map(TInput input);
}
デジタル化できなかった理由はその直接の地図 System.Converter<T>
委譲などをすることができますようなもの:
IMapper<ObjectA, ObjectB> myAToBMapper = new MyAToBMapper();
ObjectA[] aArray = { new ObjectA(), new ObjectA() };
ObjectB[] bArray = Array.ConvertAll<ObjectA, ObjectB>(aArray, myAToBMapper.Map);
List<ObjectA> aList = new List<ObjectA> { new ObjectA(), new ObjectA() };
List<ObjectB> bList = aList.ConvertAll<ObjectB>(myAToBMapper.Map);
// Or
var aToBConverter = new Converter<ObjectA, ObjectB>(myAToBMapper.Map);
bArray = Array.ConvertAll(aArray, aToBConverter);
bList = aList.ConvertAll(aToBConverter);
AutoMapper も示唆されるにつけることができます。しかしまたくマッピングの抽象化してコードagnosticへのマッピング戦略では非常に使いやすく、上記のインターフェースを注入し、ラッパAutoMapper.いまま継続して使用することができ MapAll
拡張方法を説明します。
public class AutoMapperWrapper<in TInput, out TOutput> : IMapper<TInput, TOutput>
{
public TOutput Map(TInput input)
{
return Mapper.Map<TOutput>(input);
}
}
最終語
もうまったく見るとマッピング戦略に役というドメインと力を合わせにおンマッピング戦略です。一つの例がなければならなくなるかもしれ地図から入力項目に入ります。すでに明らかにこの合戦略がしてご使用いただくことも可能となり汚.この例では、する必要がありません。
あなたの第二の例は、ほんのわずかの変更で動作します。
// you have to include the R type in the declaration of the Mapper interface
public interface IMapper<T, R> {
T Map<R>(R obj);
}
// You have to specify both IMapper implementations in the declaration
public class BillHistoryMapper : IMapper<Account, Invoice>, IMapper<Account, Payment> {
public BillHistory Map<Invoice>(Invoice obj) {
// mapping code
}
public BillHistory Map<Payment>(Payment obj) {
// mapping code
}
}
私はわからないんだけど、これは実際にかかわらず、あなたの既存のパターンの上に何かを獲得する場合。
あなたは、からマップするために、私はインターフェイス定義に入力および出力の種類を宣言する最初の方法を使用したい種類の限られた数がある場合。その後、マッパーは、あなたのBillHistoryMapper
は次のように宣言されますので、それは、サポートする各入力タイプのインタフェースを実装することができます:
public class BillHistoryMapper : IMapper<BillHistory, Invoice>, IMapper<BillHistory, Payment>
{
...
}