.NET体系结构问题:2 Web服务,如何更改运行时使用的Web服务?
-
02-07-2019 - |
题
我正在使用Reporting Services和Sharepoint,我有一个利用报告服务的应用程序,但客户希望我们的应用程序集成到sharepoint中。目前,我们与ReportService.asmx webservice紧密耦合,后者公开了各种执行操作的方法。 Reporting Services具有称为“Sharepoint集成模式”的东西。启用时,报表服务器的工作方式不同,Sharepoint用于管理报表。 Sharepoint添加了一个名为ReportService2006.asmx的新Web服务,几乎完全相同。
现在,我们的应用程序使用对ReportService的Web引用,并使用该服务公开的各种对象。 ReportService2006具有完全相同的对象,但它们显然位于不同的名称空间中,例如,我有2个Web引用 - 每个服务1个,因此有一个对象MyApplication.ReportService.CatalogItem和另一个MyApplication.ReportService2006.CatalogItem。
我尝试使用依赖注入来取消我们的应用程序和工厂模式之外的服务,以确定我实例化的接口的哪个实现。继承人我的界面。我已将其简化为仅包含此应用程序所需的调用。
using System;
using NetworkUserEncrypt.ReportService;
namespace MyApplication.Service
{
public interface IReportingService
{
CatalogItem CreateDataSource(string DataSource, string Parent, bool Overwrite, DataSourceDefinition Definition, Property[] Properties);
void DeleteItem(string Item);
DataSourceDefinition GetDataSourceContents(string DataSource);
byte[] GetReportDefinition(string Report);
CatalogItem[] ListChildren(string Item);
}
}
所以我有2个实现,每个实例化一个不同的Web服务,例如:
namespace MyApp.Service.Implementation
{
class ReportingServiceImpl : IReportingService
{
ReportingService _service = null;
public ReportingServiceImpl()
{
ReportingService _service = new ReportingService();
}
/* SNIP */
}
}
和
namespace MyApp.Service.Implementation
{
class ReportingService2006Impl : IReportingService
{
ReportingService2006 _service = null;
public ReportingService2006Impl()
{
ReportingService2006 _service = new ReportingService2006();
}
/* SNIP */
}
}
所以计划是我可以在运行时将这些注入我的ServiceWrapper。但是 - 如果您注意到该接口与ReportService绑定,并且某些方法返回来自Web引用的对象,例如: CatalogItem。因此我的项目不会构建,因为我的ReportService2006实现是从不同的命名空间引用CatalogItem。
有什么想法吗?我对这个方向走错了吗?
解决方案
最强大的解决方案是创建一个CatalogItem接口并为每个Web服务创建包装器并隐藏工厂后面的所有内容。工厂将包含用于调用“正确”的逻辑。必须更改Web服务和客户端代码才能使用界面,但这是一个更好的变化。
WCF确实解决了服务合同中的大多数问题,如果我之前的建议被证明太难以管理,您可以考虑迁移到WCF解决方案。
其他提示
我认为你正朝着正确的方向前进,这只是需要花费更多的工作才能把它带回家。我将创建一些代理类,可以使用反射或动态方法包装两个版本的类。我也看到人们使用远程命名空间中的代理类来拦截运行时的方法调用并将它们引导到正确的位置,这样你就可以按需创建动态方法而不是手动编码,所有你真正需要的是一个与对象接口匹配的接口。
添加所需的引用或为CatalogItem和其他特定类构建包装器。我构建了包装器,接口应该能够独立存在而无需引用任何特定的实现。
如果Web服务驻留在不同的名称空间中,那么就没有简单的解决方案(例如,更改URL的简单方法)。尽管如此,你似乎走在了正确的轨道上。
如果你喜欢冒险,你可以自己修改生成的Web服务类(“reference.cs”文件),然后手动将它们添加到你的项目中。首先创建一个公共接口,然后修改文件中的第一行,如:
public partial class MyWebService : SoapHttpClientProtocol, IMyWebService
然后使用它来调用代码:
IMyWebService webService = new MyWebService(); // Or you can use a Factory
在VS2008中,如果我尝试将ServiceReference添加到Web服务,我会看到一个高级按钮。点击它时,可以选择“重复使用类型”。