在 C# 中使用相同布局强制不同命名空间中的类型
我已经开始为 FedEx 的 Web 服务 API 编写接口。 他们有 3 个我感兴趣的不同 API; 费率、运送和追踪。 我正在使用 SvcUtil.exe 生成服务代理。
不同的服务端点均由 FedEx 在其自己的 WSDL 文件中指定。 每个服务端点都有自己的 xml 命名空间(例如 http://fedex.com/ws/rate/v5 和 http://fedex.com/ws/ship/v5)
服务端点执行使用相当多相同的类型,例如地址、测量、重量、身份验证详细信息、客户端详细信息等...
这就是问题所在,我可以同时向 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 吗?
I've started writing an interface for FedEx's webservice APIs. They have 3 different APIs that I'm interested in; Rate, Ship, and Track. I am generating the service proxies with SvcUtil.exe.
The different service endpoints are each specified by FedEx in their own WSDL files. Each service endpoint has it's own xml namespace (e.g. http://fedex.com/ws/rate/v5 and http://fedex.com/ws/ship/v5)
The service endpoints do use quite a few identical types such as Address, Measurements, Weight, AuthenticationDetail, ClientDetail, etc...
And here is where the problem lies, I can provide all the WSDL files at the same time to SvcUtil.exe and normally it would coalesce any identical types into a single shared type, but since each of FedEx's services are in their own namespace, and they redeclare these types in each WSDL file under that namespace what I end up with instead is an Address, Address1, and Address2 one for each namespace.
To solve that issue, what I do now is to run each WSDL through svcutil separately and put them each in their own .NET namespace (e.g. FedEx.Rate, FedEx.Ship, FedEx.Track). The problem with this is that now I have a distinct address type in each namespace (Fedex.Rate.Address, FedEx.Ship.Address).
This makes it difficult to generalize the code used between the services like a GetAuthenticationDetail() factory method so I don't have to repeat that code in every place I use the different services.
Is there any way in C# to Coerce FedEx.Rate.Address to FedEx.Ship.Address?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果类型相同,并且您可以控制源类,则可以定义 类中的转换运算符,任何采用
Rate.Address
的函数也将自动采用Ship.Address
。 例如:我的 C# 有点生疏,但我希望你能明白。
If the types are identical, and you have control over the source classes, you can define a conversion operator in the class, and any function that takes a
Rate.Address
will also automatically take aShip.Address
. For example:My C# is a little rusty but I hope you get the idea.
以下是我如何使用反射实现隐式转换运算符。 SvcUtil 创建部分类,因此我为每个转换方向添加了一个隐式转换运算符,因此在客户端代码中您只需键入
Type1 = Type2
。在此代码片段中,WebAuthenticationCredentials 是 WebAuthenticationDetails 的属性,因此在迭代源对象的属性时,如果类型不相同(内置),它会检查类型的名称(不带命名空间)并使用这些属性递归调用复制函数。
So here is how I implemented the implicit conversion operators using reflection. SvcUtil creates partial classes so I added an implicit conversion operator for each direction of the conversion so in the client code you can just type
Type1 = Type2
.In this snippet WebAuthenticationCredentials is a property of WebAuthenticationDetails so while iterating the properties of the source object if the types arent the same (built-ins) it checks the name of the types (without the namespace) and recursively calls the copy function with those properties.
您可以通过创建自己的 Address 实现来使用运算符重载,或者使用其中一种稳定类型作为属性,
例如:下面的 Address1 和 Address2 分别是您的 Rate.Address 和 Ship.Address
编辑:方法与帖子相同上面,实现是在一个单独的类中,仅此而已
you could use operator overloading by creating your own implementation of Address or use one of the stable types as a property
one example: Address1 and Address2 below would be your Rate.Address and Ship.Address respectively
Edit: the approach is the same as the post above, the implementation is in a seperate class thats all
这些生成的类是否定义为“部分”? 如果是这样,您可以在不同的文件中扩展它们并提取一个接口并让所有 Address 类实现它。
Are those generated classes defined as "partial" ? If so, you could extend them in a different file and extract an interface and let it be implemented by all Address classes.