Я работаю с Reporting Services и Sharepoint, у меня есть приложение, которое использует службы отчетов, однако клиент хотел бы, чтобы наше приложение было интегрировано в sharepoint. В настоящее время мы тесно связаны с веб-сервисом ReportService.asmx, который предоставляет различные методы для выполнения операций. В службах Reporting Services есть так называемый «режим интеграции Sharepoint», когда он включен, сервер отчетов работает иначе, а для управления отчетами используется Sharepoint. Sharepoint добавляет новую веб-службу ReportService2006.asmx, которая почти такая же.
Теперь наше приложение использует веб-ссылку на ReportService и различные объекты, предоставляемые службой. ReportService2006 имеет точно такие же объекты, но они, очевидно, находятся в другом пространстве имен, например, у меня есть 2 веб-ссылки - по одной на каждую службу, поэтому есть объект 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 реализации этого, каждая из которых создает экземпляр другой веб-службы, например:
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 из другого пространства имен.
Есть идеи? Я иду в неправильном направлении?





Я думаю, что вы движетесь в правильном направлении для этой ситуации. Просто нужно приложить немало усилий, чтобы довести дело до дома. Я бы создал несколько прокси-классов, которые могут обернуть обе версии классов с помощью отражения или динамических методов. Я также видел, как люди используют прокси-классы из пространства имен удаленного взаимодействия, чтобы перехватывать вызовы методов во время выполнения и направлять их в нужное место, чтобы вы могли создавать динамические методы по запросу вместо их ручного кодирования, все, что вам действительно нужно для этого - это интерфейс, соответствующий интерфейсу объекта.
Либо добавьте необходимую ссылку, либо создайте оболочки для CatalogItem и остальных конкретных классов. Я бы построил обертки, интерфейс должен иметь возможность работать самостоятельно, без ссылки на какую-либо конкретную реализацию.
Если веб-службы находятся в разных пространствах имен, тогда нет тривиального решения (например, чего-то столь же простого, как изменение URL-адреса). Однако в абстракции вы, кажется, на правильном пути.
Тем не менее, если вы любите приключения, вы можете самостоятельно изменить сгенерированные классы веб-служб (файлы «reference.cs»), а затем вручную добавить их в свой проект. Сначала создайте общий интерфейс, затем измените первые строки в файле следующим образом:
public partial class MyWebService : SoapHttpClientProtocol, IMyWebService
Затем вы используете это для вызова кода:
IMyWebService webService = new MyWebService(); // Or you can use a Factory
В VS2008, если я пытаюсь добавить ServiceReference к веб-сервису, я вижу расширенную кнопку. При нажатии на нее появляется возможность «повторно использовать типы».
Наиболее надежное решение - создать интерфейс CatalogItem и создать оболочки для каждой из ваших веб-служб и спрятать все это за фабрикой. Фабрика будет содержать логику для вызова «правильной» веб-службы, а для использования интерфейса необходимо будет изменить код клиента, но это изменение к лучшему.
WCF решает большинство этих проблем с помощью контрактов на обслуживание, и если мой предыдущий совет окажется слишком неуправляемым, вы можете подумать о переходе на решение WCF.