我已经开始为FedEx的webservice API编写一个接口.他们有3种不同的API,我很感兴趣; 费率,发货和跟踪.我正在使用SvcUtil.exe生成服务代理.
FedEx在自己的WSDL文件中指定了不同的服务端点.每个服务端点都有自己的xml命名空间(例如http://fedex.com/ws/rate/v5和http://fedex.com/ws/ship/v5)
服务端点确实使用了相当多的相同类型,例如Address,Measurements,Weight,AuthenticationDetail,ClientDetail等......
这就是问题所在,我可以同时向SvcUtil.exe提供所有WSDL文件,通常它会将任何相同的类型合并为一个共享类型,但由于FedEx的每个服务都在它们自己的命名空间中,他们在该命名空间下的每个WSDL文件中重新声明这些类型,而不是每个命名空间的Address,Address1和Address2.
为了解决这个问题,我现在要做的是分别通过svcutil运行每个WSDL,并将它们分别放在自己的.NET命名空间中(例如FedEx.Rate,FedEx.Ship,FedEx.Track).这个问题是现在我在每个命名空间中都有一个不同的地址类型(Fedex.Rate.Address,FedEx.Ship.Address).
这使得很难概括像GetAuthenticationDetail()工厂方法之类的服务之间使用的代码,因此我不必在每个使用不同服务的地方重复该代码.
在C#中是否有任何方法可以将FedEx.Rate.Address强制转换为FedEx.Ship.Address?
如果类型相同,并且您可以控制源类,则可以在类中定义转换运算符,并且任何带有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#有点生疏,但我希望你明白这个想法.
所以这是我如何使用反射实现隐式转换运算符.SvcUtil创建了部分类,因此我为每个转换方向添加了一个隐式转换运算符,因此在客户端代码中您只需键入即可Type1 = Type2
.
在这个片段中,WebAuthenticationCredentials是WebAuthenticationDetails的一个属性,因此如果类型不同(内置函数),则迭代源对象的属性时,它会检查类型的名称(没有命名空间),并使用这些属性递归调用复制函数.
internal class ReflectionCopy { public static ToType Copy(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 (from); } } partial class WebAuthenticationCredential { public static implicit operator Ship.WebAuthenticationCredential(WebAuthenticationCredential from) { return ReflectionCopy.Copy (from); } } } namespace Ship { partial class WebAuthenticationDetail { public static implicit operator Rate.WebAuthenticationDetail(WebAuthenticationDetail from) { return ReflectionCopy.Copy (from); } } partial class WebAuthenticationCredential { public static implicit operator Rate.WebAuthenticationCredential(WebAuthenticationCredential from) { return ReflectionCopy.Copy (from); } } }