Архитектурная проблема .NET: 2 веб-службы, как мне изменить, какой из них используется во время выполнения? - PullRequest
1 голос
/ 26 сентября 2008

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

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

Ответы [ 5 ]

1 голос
/ 26 сентября 2008

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

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

1 голос
/ 26 сентября 2008

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

1 голос
/ 26 сентября 2008

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

1 голос
/ 26 сентября 2008

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

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

public partial class MyWebService : SoapHttpClientProtocol, IMyWebService

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

IMyWebService webService = new MyWebService();  // Or you can use a Factory
1 голос
/ 26 сентября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...