C# .NET体系结构问题:2 Web服务,如何更改运行时使用的服务?
我正在使用Reporting Services和Sharepoint,我有一个利用Reporting Services的应用程序,但是客户希望我们的应用程序集成到Sharepoint中。目前,我们与ReportService.asmx webservice紧密耦合,它公开了执行操作的各种方法。如果启用Reporting Services,则称为Sharepoint集成模式。报表服务器的工作方式不同,Sharepoint用于管理报表。Sharepoint添加了一个名为ReportService2006.asmx的新web服务,该服务几乎完全相同 现在,我们的应用程序使用对ReportService的web引用,并使用服务公开的各种对象。ReportService2006具有完全相同的对象,但它们显然位于不同的命名空间中。例如,我有2个web引用-每个服务1个,因此有一个对象MyApplication.ReportService.CatalogItem和另一个对象MyApplication.ReportService2006.CatalogItem 我曾尝试使用依赖注入将服务从应用程序中分离出来,并使用工厂模式来确定要实例化的接口实现。这是我的界面。我已将其简化为只包含此应用程序所需的调用C# .NET体系结构问题:2 Web服务,如何更改运行时使用的服务?,c#,.net,sharepoint,architecture,reporting-services,C#,.net,Sharepoint,Architecture,Reporting Services,我正在使用Reporting Services和Sharepoint,我有一个利用Reporting Services的应用程序,但是客户希望我们的应用程序集成到Sharepoint中。目前,我们与ReportService.asmx webservice紧密耦合,它公开了执行操作的各种方法。如果启用Reporting Services,则称为Sharepoint集成模式。报表服务器的工作方式不同,Sharepoint用于管理报表。Sharepoint添加了一个名为ReportService20
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);
}
}
因此,我有两个实现,每个实现实例化一个不同的web服务,例如:
namespace MyApp.Service.Implementation
{
class ReportingServiceImpl : IReportingService
{
ReportingService _service = null;
public ReportingServiceImpl()
{
ReportingService _service = new ReportingService();
}
/* SNIP */
}
}
及
所以计划是我可以在运行时将这些注入到我的ServiceWrapper中。但是,如果您注意到该接口与ReportService绑定,并且某些方法返回来自web引用的对象,例如CatalogItem。因此,我的项目将不会生成,因为我的ReportService2006实现正在引用来自不同命名空间的CatalogItem
有什么想法吗?我完全走错方向了吗?我认为你在这种情况下走的方向是正确的,只是需要做更多的工作才能把它带回家。我将创建一些代理类,它们可以使用反射或动态方法包装这两个版本的类。我还看到人们使用远程名称空间中的代理类在运行时拦截方法调用并将它们定向到正确的位置,这样您就可以根据需要创建动态方法,而不是手工编写它们,您真正需要的是一个与对象接口相匹配的接口。我认为您在这种情况下朝着正确的方向前进,只是需要做更多的工作才能将其实现。我将创建一些代理类,它们可以使用反射或动态方法包装这两个版本的类。我还看到人们使用远程名称空间中的代理类在运行时拦截方法调用并将它们定向到正确的位置,这样您就可以根据需要创建动态方法,而不是手工编写它们,您真正需要的只是一个与对象接口匹配的接口。添加它所需的引用,或者为CatalogItem和其他特定类构建包装。如果我构建包装器,接口应该能够独立运行,而无需引用任何特定的实现。要么添加它所需的引用,要么为CatalogItem和其他特定类构建包装器。我会构建包装器,接口应该能够独立运行,而无需引用任何特定的实现。如果Web服务驻留在不同的名称空间中,那么就没有简单的解决方案,例如更改URL这样简单的事情。不过,你在抽象方面似乎走对了方向 但是,如果您觉得有冒险精神,您可以自己修改生成的Web服务类,修改reference.cs文件,然后手动将它们添加到项目中。首先创建一个公共接口,然后修改文件中的第一行,如下所示:
public partial class MyWebService : SoapHttpClientProtocol, IMyWebService
然后,使用此函数调用代码:
IMyWebService webService = new MyWebService(); // Or you can use a Factory
如果Web服务驻留在不同的名称空间中,那么就没有简单的解决方案,例如更改URL这样简单的事情。不过,你在抽象方面似乎走对了方向 但是,如果您觉得有冒险精神,您可以自己修改生成的Web服务类,修改reference.cs文件,然后手动将它们添加到项目中。首先创建一个公共接口,然后修改文件中的第一行,如下所示:
public partial class MyWebService : SoapHttpClientProtocol, IMyWebService
然后,使用此函数调用代码:
IMyWebService webService = new MyWebService(); // Or you can use a Factory
在VS2008中,如果我尝试向Web服务添加ServiceReference,我会看到一个高级按钮。单击它时,有一个重复使用类型的选项。在VS2008中,如果我尝试向Web服务添加ServiceReference,我会看到一个高级按钮。单击它时,可以选择重复使用类型。最可靠的解决方案是创建CatalogItem接口,为每个web服务创建包装,并将整个内容隐藏在工厂后面。工厂将包含调用正确web服务的逻辑 nd客户端代码必须更改才能使用接口,但这是一个更好的更改
WCF确实用服务合同解决了这些问题,如果我之前的建议太难管理,您可以考虑迁移到WCF解决方案。
< P>最健壮的解决方案是创建目录项接口并为每个Web服务创建包装器,并将整个事情隐藏在工厂后面。工厂将包含调用正确web服务的逻辑,必须更改客户端代码才能使用该接口,但这是一个更好的更改WCF确实用服务合同解决了这些问题,如果我之前的建议太难管理,您可以考虑迁移到WCF解决方案。