在.NET應用程序中,我使用了兩個遠程WCF服務,它們都具有「相同」對象的定義:CoreService.Customer
和ProductService.Customer
。通過強制轉換重複使用相同的函數,或者使用鴨子鍵入不同的對象類型
「相同」是故意放在引號;從名稱空間的角度來看,它們是兩個不同的實體。但是,這是純粹的,因爲服務的生成/消耗方式。在這種情況下,兩個對象都來自後端系統中的相同庫是一個給定的事實。
在特定場景中,我需要從兩種對象類型中提取內容。我這是最初建於一個特定的實例中的一個功能:
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);
}
,這個作品其實是有道理的,考慮到性能並且兩個對象的值保證是匹配的。雖然,這是昂貴的,似乎很沒必要。
另一種選擇是使用implicit conversion operator。但是,考慮到對象是服務生成的,我不太清楚如何使用操作符來擴展這兩個對象。
關於這是不是最佳實踐,關鍵不在於辯論。也不知道如何找到像在不同的服務引用之間重複使用相同的共享對象的選擇。我很清楚這種黑客的尷尬。只要說從語言的角度來看,我覺得這是一個有趣的挑戰就足夠了。
這讓我想起了實際的問題:有沒有更優雅的方式愚弄編譯器吞噬這個或更好的投入,使兩個「不同但相同」的對象之間更便宜的投/允許我重新使用_ExtractFoo()
實現?
更新I -使外部Web服務使用通用接口不是一個選項。此外,可能很高興知道Customer對象具有相當深層次的嵌套屬性和子對象;使用類似AutoMapper的東西,或手動地圖,會很麻煩(更不用說容易出錯)。
更新II -對於將來參考起見,我試圖解釋,我的問題/問題是我怎麼能修改_ExtractFoo()
方法 - 或其執行 - 因此它可以被應用到CoreService.Customer
和ProductService.Customer
(攝以上的一切考慮在內)。從「請列出所有其他選項」的意義上來說,這絕對不是一個開放的問題,儘管在我看來,答案中提供的答案在選項上當然是可行的。
假設你不能讓兩個對象實現相同的接口? – DavidG
事實上,這不是一個不幸的選擇。 –
這個問題看起來非常廣泛。細節太少,我們不得不推斷太多,導致太多可能的答案。也就是說,在C#中,「duck typing」通常意味着你想使用'dynamic'。上面使用'dynamic'的唯一示例,它看起來並不像你做得正確。 「動態」的重點不是強制轉換爲特定類型,而是要訪問您希望存在的指定成員。即**鴨打字**。只要你選擇了某種特定的類型,就會失敗,因爲你剛剛回到了傳統C#的靜態類型世界。 –