專案中發現同一數據契約在客戶端屬於兩個不同命名空間,導致兩服務交互時類型不匹配,互操作性差,需額外拆裝轉換。以下重現場景:
namespace GaryChenWCFService {
public class Customer {
public string Name { get; set; }
public string Sex { get; set; }
}
}
namespace GaryChenWCFService.ServiceClasses {
public class OneCustomerService : ServiceContracts.IOneCustomer {
public GaryChenWCFService.Customer GetCustomer() { /*...*/ }
}
}
namespace GaryChenWCFService.ServiceClasses {
public class TwoCustomerService : ServiceContracts.ITwoCustomer {
public void AddCustomer(GaryChenWCFService.Customer cs) { /*...*/ }
}
}
OneCustomerService_Proxy.OneCustomerClient OneService_Proxy = new ...();
TwoCustomerService_Proxy.TwoCustomerClient TwoService_Proxy = new ...();
OneCustomerService_Proxy.Customer cu = OneService_Proxy.GetCustomer();
TwoService_Proxy.AddCustomer(cu); // 編譯錯誤:類型不匹配
服務 1 返回的 Customer 屬於 OneCustomerService_Proxy 命名空間,服務 2 期望 TwoCustomerService_Proxy.Customer。雖代表同一數據契約,但代理生成的類型不同(見物件瀏覽器截圖),須顯式轉換,極不便利。

《WCF 編程第二版》指出:VS 2008 添加服務引用時,必須為每個引用提供唯一命名空間。若兩服務共享相同數據契約,會得到兩個不同命名空間的類型。預設情況下,若客戶端引用的任意程序集包含與服務元數據匹配的數據契約,VS 不會重新導入。**關鍵限制:已有的數據契約引用必須在另一個被引用程序集中,而非客戶端專案本身。**
最佳實踐:將所有共享數據契約分解到專門類庫,讓所有客戶端引用該程序集。然後在服務引用的「進階設定」對話框中,勾選「Reuse types in referenced assemblies」(預設勾選),控制引用程序集與共享數據契約協調。單選按鈕可限制跨所有引用程序集重用或特定程序集。注意:只能共享數據契約,不能共享服務契約。

這做法需將服務端 DLL 分發給客戶端,對異構平台調用極不合理。但若客戶端同為 .NET 自主開發,這是無奈之舉。期待 WCF 未來版本改進此點!