.NETアプリケーションでは、「同じ」オブジェクトの定義を持つ2つのリモートWCFサービスを消費しています。CoreService.Customer
およびProductService.Customer
。同じ関数をキャストしたり、別のオブジェクト型を入力するダック
「同じ」という言葉は意図的に引用符で囲まれています。名前空間の観点からは、それらは2つの異なるエンティティです。しかし、これは、サービスが生成/消費される方法のために純粋です。この状況では、両方のオブジェクトがバックエンドシステム内の同じライブラリに由来するという事実があります。
具体的なシナリオでは、両方のオブジェクトタイプから要素を抽出する必要があります。私がしたいことは、過負荷を提供することで、鋳造やボクシングの方法により、同じ操作を再利用するために実際にある
private static string _ExtractFoo(CoreService.Customer customer) {
// removed for the sake of brevity
return string.Empty;
}
単に両方のコンパイラを説得しよう:私はもともと一つの特定のインスタンスのために構築された単一の機能を持っていますこれがちょうどうまくいく(あなたがすれば単にduck typingと思ってください)。
次のシナリオのが動作しません:
private static string _ExtractFoo(ProductService.Customer customer) {
// #1 - Cast, results in error:
// Cannot convert type ... via a built-in conversion
return _ExtractFoo((CoreService.Customer) customer);
// #2 - Safe cast, results in error:
// Cannot convert type ... via a built-in conversion
return _ExtractFoo(customer as CoreService.Customer);
// #3 - Works for compiler, breaks at runtime where 'casted' is null
dynamic d = customer;
var casted = d as CoreService.Customer;
return _ExtractFoo(casted);
}
仕事が最初にJSONにシリアライズされない簡単な修正:
private static string _ExtractFoo(ProductService.Customer customer) {
// awkward hack - but it blends!
var serialized = JsonConvert.SerializeObject(customer);
var deserialized = JsonConvert.DeserializeObject<CoreService.Customer>(serialized);
return _ExtractFoo(deserialized);
}
この作品は、性質を考慮すると、理にかなっているという事実両方のオブジェクトの値が一致することが保証されています。しかし、これは高価であり、かなり不必要なようです。
もう1つのオプションはimplicit conversion operatorです。しかし、オブジェクトがサービス生成されていることを考えると、私は両方のオブジェクトを演算子で拡張する方法はよく見ていません。
これがベストプラクティスであるかどうかは、主なポイントは議論の余地がありません。異なるサービス参照間で同じ共有オブジェクトを再利用するような選択肢を見つける方法もありません。私はこのハックの厄介さをよく知っています。私はそれが言語の観点から興味深い課題であると言えば十分です。
そして、それは実際の質問に私をもたらします:2「異なるが、同じ」オブジェクト間で安価なキャスト/ボクシングを作り、これを嚥下にコンパイラをだますために、よりエレガントな方法または、より良いプットがあり、 _ExtractFoo()
の実装を再利用できるようにしますか?
更新I -外部Webサービスを使用する場合、共通のインタフェースを使用することはオプションではありません。また、Customerオブジェクトには、ネストされたプロパティと子オブジェクトのかなり深い階層があることがわかります。 AutoMapperやマニュアルマップのようなものを使うと面倒です(エラーが発生しにくいことは言うまでもありません)。
アップデートII - またはその実装 - -将来の参考のために、私は/質問私の問題は、私は_ExtractFoo()
方法を変更することができる方法であることを説明しようとしたので、それはCoreService.Customer
とProductService.Customer
の両方に適用することができます(とら上記のすべてを考慮してください)。答えとして提供されているものは私の意見では確かに選択肢として実行可能ですが、「他のすべての選択肢を挙げてください」という意味で未解決の質問であることは間違いありません。私の頭の上オフ
両方のオブジェクトで同じインターフェイスを実装することはできないとしますか? – DavidG
実際、それは残念なことにオプションではありません。 –
質問は非常に広いようです。詳細はほとんどないので、あまりにも多くを推論しなければならず、それは可能な限り多くの回答につながります。つまり、C#の "duck typing"では、一般的に 'dynamic'を使いたいということです。上の唯一の例は、 'dynamic'を使うところです。正しく行ったようには見えません。 'dynamic'の全体的なポイントは、特定の型にキャストするのではなく、存在すると期待される名前付きメンバにアクセスすることです。私。 **アヒルタイピング**。特定のタイプにキャストするとすぐに、あなたは失われるでしょう。なぜなら、従来型のC#の静的型の世界に戻ったからです。 –