1

我正在使用 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。

有任何想法吗?我的方向完全错误吗?

4

5 回答 5

1

对于这种情况,我认为您正朝着正确的方向前进,只是需要做更多的工作才能将其带回家。我会创建一些代理类,它们可以使用反射或动态方法包装两个版本的类。我还看到人们使用远程命名空间中的代理类在运行时拦截方法调用并将它们定向到正确的位置,这样您就可以按需创建动态方法而不是手动编码它们,这一切都是您真正需要的是一个与对象的接口相匹配的接口。

于 2008-09-26T14:08:32.170 回答
1

要么添加它需要的引用,要么为 CatalogItem 和其余特定类构建包装器。我会构建包装器,接口应该能够独立存在而不引用任何特定的实现。

于 2008-09-26T14:10:07.817 回答
1

如果 Web 服务驻留在不同的名称空间中,那么就没有简单的解决方案(例如,像更改 URL 这样简单的事情)。不过,您似乎在抽象的正确轨道上。

如果您喜欢冒险,您可以自己修改生成的 Web 服务类(“reference.cs”文件),然后手动将它们添加到您的项目中。首先创建一个通用接口,然后修改文件中的第一行,如下所示:

public partial class MyWebService : SoapHttpClientProtocol, IMyWebService

然后你用它来调用代码:

IMyWebService webService = new MyWebService();  // Or you can use a Factory
于 2008-09-26T14:18:23.363 回答
1

在 VS2008 中,如果我尝试将 ServiceReference 添加到 Web 服务,我会看到一个高级按钮。单击它时,有一个“重用类型”的选项。

于 2008-09-26T14:19:23.160 回答
1

最强大的解决方案是创建一个 CatalogItem 接口并为每个 Web 服务创建包装器,并将整个事物隐藏在工厂后面。工厂将包含调用“正确”Web 服务的逻辑,并且必须更改客户端代码才能使用该接口,但这是一个更好的更改。

WCF 确实通过服务合同解决了大多数这些问题,如果我之前的建议被证明太难以管理,您可以考虑迁移到 WCF 解决方案。

于 2008-09-26T16:03:49.837 回答