2009-02-18 67 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); 
     } 
    } 
} 
相关问题