Архитектурная проблема .NET:2 Веб-службы. Как изменить, какая из них будет использоваться во время выполнения?

StackOverflow https://stackoverflow.com/questions/139639

Вопрос

Я работаю с Reporting Services и Sharepoint. У меня есть приложение, которое использует службы отчетов, однако клиент хотел бы, чтобы наше приложение было интегрировано в SharePoint.В настоящее время мы тесно связаны с веб-сервисом ReportService.asmx, который предоставляет различные методы выполнения операций.В службах Reporting Services есть так называемый «режим интеграции с SharePoint», когда он включен, сервер отчетов работает по-другому, и для управления отчетами используется Sharepoint.Sharepoint добавляет новую веб-службу ReportService2006.asmx, которая практически аналогична.

Теперь наше приложение использует веб-ссылку на ReportService и различные объекты, предоставляемые этой службой.ReportService2006 имеет точно такие же объекты, но они, очевидно, находятся в другом пространстве имен. Например, у меня есть 2 веб-ссылки - по 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);
    }
}

Итак, у меня есть две реализации, каждая из которых создает экземпляр другого веб-сервиса, например:

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, а некоторые методы возвращают объекты из веб-ссылки, например.КаталогЭлемент.Таким образом, мой проект не будет собран, поскольку моя реализация ReportService2006 ссылается на CatalogItem из другого пространства имен.

Есть идеи?Я иду совершенно в неправильном направлении?

Это было полезно?

Решение

Самое надежное решение — создать интерфейс CatalogItem, создать обертки для каждого из ваших веб-сервисов и спрятать все это за фабрикой.Фабрика будет содержать логику для вызова «правильного» веб-сервиса, и для использования интерфейса придется изменить клиентский код, но это изменение к лучшему.

WCF действительно решает большинство этих проблем с помощью сервисных контрактов, и если мой предыдущий совет окажется слишком невыполнимым, вы можете рассмотреть возможность перехода к решению WCF.

Другие советы

Я думаю, что вы движетесь в правильном направлении в этой ситуации. Просто потребуется гораздо больше работы, чтобы довести ее до конца.Я бы создал несколько прокси-классов, которые могли бы обертывать обе версии классов, используя отражение или динамические методы.Я также видел, как люди использовали прокси-классы из пространства имен удаленного взаимодействия для перехвата вызовов методов во время выполнения и направления их в нужное место. Таким образом, вы могли бы создавать динамические методы по требованию, а не писать их вручную, и все, что вам действительно нужно для этого. — это интерфейс, соответствующий интерфейсу объекта.

Либо добавьте необходимую ссылку, либо создайте оболочки для CatalogItem и остальных конкретных классов.Я бы создал обертки, интерфейс должен быть самостоятельным, не ссылаясь на какую-либо конкретную реализацию.

Если веб-службы находятся в разных пространствах имен, то тривиального решения не существует (например.что-то простое, например изменение URL-адреса).Хотя с абстракцией вы, похоже, на правильном пути.

Однако если вы любите приключения, вы можете самостоятельно изменить сгенерированные классы веб-служб (файлы «reference.cs»), а затем вручную добавить их в свой проект.Сначала создайте общий интерфейс, затем измените первые строки файла следующим образом:

public partial class MyWebService : SoapHttpClientProtocol, IMyWebService

Затем вы используете это для вызова кода:

IMyWebService webService = new MyWebService();  // Or you can use a Factory

В VS2008, если я попытаюсь добавить ServiceReference к веб-сервису, я увижу кнопку «Дополнительно».При нажатии на нее появляется возможность «повторно использовать типы».

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top