2009-02-18 60 views
12

我已經開始爲FedEx的webservice API編寫接口。他們有我感興趣的3種不同的API;費率,運送和跟蹤。我正在使用SvcUtil.exe生成服務代理。Coerce類型在C#中具有相同佈局的不同命名空間中

FedEx在各自的WSDL文件中指定了不同的服務端點。每個服務端點都有它自己的XML命名空間(如http://fedex.com/ws/rate/v5http://fedex.com/ws/ship/v5

服務端點確實使用了不少相同的類型,如地址,測量,重量,AuthenticationDetail,ClientDetail等..

這裏問題在哪裏,我可以同時向SvcUtil.exe提供所有WSDL文件,通常它會將任何相同類型合併爲一個共享類型,但由於FedEx的每個服務都位於其自己的命名空間中,因此它們會重新聲明這些名稱空間下的每個WSDL文件中的這些類型,而我最終將爲每個名稱空間分配一個地址,地址1和地址2。

爲了解決這個問題,我現在要做的是通過svcutil單獨運行每個WSDL,並將它們分別放在它們自己的.NET名稱空間(例如FedEx.Rate,FedEx.Ship,FedEx.Track)中。與此問題是,現在我在每個名稱空間(Fedex.Rate.Address,FedEx.Ship.Address)中有一個不同的地址類型。

這使得在GetAuthenticationDetail()工廠方法之類的服務之間使用的代碼變得很難推廣,所以我不必在每個使用不同服務的地方重複使用代碼。

有沒有什麼辦法在C#中強制FedEx.Rate.Address到FedEx.Ship.Address?

+0

+1。我正在努力解決同樣的問題,從來沒有找到一個很好的解決方案。 – 2009-02-18 19:53:08

+0

偉大的問題;我以爲我錯誤地導入了WSDL,直到我看得更近,而且他們確實爲不同的名稱空間分配了相同的類型。 – 2009-07-16 00:01:19

回答

8

如果類型是相同的,並且您有源類切換控制中,可以定義在類一個conversion operator,而這需要一個Rate.Address也會自動採取Ship.Address任何功能。例如:

namespace Rate { 
    class Address { 
     string Street; 
     string City; 
     // ... 

     public static implicit operator Ship.Address(Rate.Address addr) { 
      Ship.Address ret; 
      ret.Street = addr.Street; 
      ret.City = addr.City; 
      // ... 

      return ret; 
     } 
    } 
} 

我的C#有點生疏,但我希望你明白了。

+0

這種方法存在問題。例如,如果WSDL發生變化(添加了一些屬性),並使用svcutil.exe重新生成代理,則不必忘記更新隱式操作方法,否則在運行時可能會出現一些奇怪的行爲。 – 2009-02-18 20:01:17

+0

嗯,我喜歡這種方法,我甚至在幾周前閱讀了C#中的轉換運算符。讓我試試看。聯邦快遞的網絡服務的一個好處是,當他們發佈新版本時,舊版仍然無限期地發揮作用。所以darin的評論不會導致我太多的問題 – joshperry 2009-02-18 20:04:00

1

你可以使用運算符重載通過創建自己的實現地址或使用穩定的類型之一作爲屬性

一個例子:地址1和地址2下面將分別

您Rate.Address和Ship.Address
class Address1 
{ 
    public string name = "Address1"; 
} 
class Address2 
{ 
    public string name = "Address2"; 
} 

class GenericAddress 
{ 
    public string name = "GenericAddress"; 
    public static implicit operator GenericAddress(Address1 a) 
    { 
     GenericAddress p = new GenericAddress(); p.name = a.name; return p; 
    } 
    public static implicit operator GenericAddress(Address2 a) 
    { 
     GenericAddress p = new GenericAddress(); p.name = a.name; return p; 
    } 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     PrintName(new Address1());//prints address1 
     PrintName(new Address2());//prints address2 
    } 

    static void PrintName(GenericAddress a) 
    { 
     Console.WriteLine(a.name); 
    } 
} 

編輯:該方法是一樣的支柱上方,實現是在一個單獨的類就是所有

1

被定義爲「部分」這些生成的類?如果是這樣,你可以擴展它們在不同的文件中,並提取一個接口,讓它由所有地址類實現。

7

因此,這裏是我如何使用反射來實現的隱式轉換操作符。 SvcUtil工具創建部分類,所以我說的隱式轉換操作的轉換的每一個方向,以便在客戶端代碼可以只鍵入Type1 = Type2

在這個片段中WebAuthenticationCredentials是WebAuthenticationDetails的屬性,以便在迭代如果類型的arent相同(內建)源對象的屬性,它會檢查該類型的名稱(沒有命名空間)和遞歸調用複製功能與這些屬性。

internal class ReflectionCopy 
{ 
    public static ToType Copy<ToType>(object from) where ToType : new() 
    { 
     return (ToType)Copy(typeof(ToType), from); 
    } 

    public static object Copy(Type totype, object from) 
    { 
     object to = Activator.CreateInstance(totype); 

     PropertyInfo[] tpis = totype.GetProperties(BindingFlags.Public | BindingFlags.Instance); 
     PropertyInfo[] fpis = from.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 

     // Go through each property on the "to" object 
     Array.ForEach(tpis, tpi => 
     { 
      // Find a matching property by name on the "from" object 
      PropertyInfo fpi = Array.Find(fpis, pi => pi.Name == tpi.Name); 
      if (fpi != null) 
      { 
       // Do the source and destination have identical types (built-ins)? 
       if (fpi.PropertyType == tpi.PropertyType) 
       { 
        // Transfer the value 
        tpi.SetValue(to, fpi.GetValue(from, null), null); 
       } 
       else 
       { 
        // If type names are the same (ignoring namespace) copy them recursively 
        if (fpi.PropertyType.Name == tpi.PropertyType.Name) 
         tpi.SetValue(to, Copy(fpi.PropertyType, tpi.GetValue(from, null)), null); 
       } 
      } 
     }); 

     return to; 
    } 
} 

namespace Rate 
{ 
    partial class WebAuthenticationDetail 
    { 
     public static implicit operator Ship.WebAuthenticationDetail(WebAuthenticationDetail from) 
     { 
      return ReflectionCopy.Copy<Ship.WebAuthenticationDetail>(from); 
     } 
    } 

    partial class WebAuthenticationCredential 
    { 
     public static implicit operator Ship.WebAuthenticationCredential(WebAuthenticationCredential from) 
     { 
      return ReflectionCopy.Copy<Ship.WebAuthenticationCredential>(from); 
     } 
    } 
} 

namespace Ship 
{ 
    partial class WebAuthenticationDetail 
    { 
     public static implicit operator Rate.WebAuthenticationDetail(WebAuthenticationDetail from) 
     { 
      return ReflectionCopy.Copy<Rate.WebAuthenticationDetail>(from); 
     } 
    } 

    partial class WebAuthenticationCredential 
    { 
     public static implicit operator Rate.WebAuthenticationCredential(WebAuthenticationCredential from) 
     { 
      return ReflectionCopy.Copy<Rate.WebAuthenticationCredential>(from); 
     } 
    } 
} 
相關問題