Problème architectural .NET: 2 Web Services, comment puis-je changer celui qui est utilisé au moment de l'exécution?

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

Question

Je travaille avec Reporting Services et Sharepoint. J'ai une application qui exploite les services de génération de rapports, mais un client souhaite que notre application soit intégrée à sharepoint. Actuellement, nous sommes étroitement associés au service Web ReportService.asmx, qui expose diverses méthodes pour effectuer des opérations. Reporting Services a un élément appelé "Mode d'intégration Sharepoint". lorsqu'il est activé, le serveur de rapports fonctionne différemment et Sharepoint est utilisé pour gérer les rapports. Sharepoint ajoute un nouveau service Web appelé ReportService2006.asmx qui est presque identique.

Notre application utilise maintenant une référence Web au ReportService et utilise divers objets exposés par le service. ReportService2006 a exactement les mêmes objets mais ils sont évidemment dans un espace de noms différent, par exemple, j'ai 2 références Web - 1 pour chaque service. Il existe donc un objet MyApplication.ReportService.CatalogItem et un autre MyApplication.ReportService2006.CatalogItem.

J'ai essayé d'utiliser l'injection de dépendance pour extraire le service de notre application, associée à un modèle d'usine afin de déterminer la mise en œuvre de mon interface à instancier. Heres mon interface. Je l'ai simplifié pour n'inclure que les appels dont j'ai besoin pour cette application.

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);
    }
}

J'ai donc 2 implémentations de cette chacune instanciant un service Web différent, par exemple:

namespace MyApp.Service.Implementation
{
    class ReportingServiceImpl : IReportingService
    {
        ReportingService _service = null;

        public ReportingServiceImpl()
        {
            ReportingService _service = new ReportingService();
        }

        /* SNIP */
    }
  }

et

namespace MyApp.Service.Implementation
{
    class ReportingService2006Impl : IReportingService
    {
        ReportingService2006 _service = null;

        public ReportingService2006Impl()
        {
            ReportingService2006 _service = new ReportingService2006();
        }

        /* SNIP */
    }
  }

Le plan est donc que je peux les injecter dans mon ServiceWrapper au moment de l'exécution. Toutefois, si vous remarquez que l’interface est liée au ReportService et que certaines méthodes renvoient des objets provenant de la référence Web, par exemple. CatalogItem. Ainsi, mon projet ne sera pas généré car mon implémentation pour ReportService2006 fait référence à CatalogItem à partir d'un espace de nom différent.

Des idées? Est-ce que je vais totalement dans la mauvaise direction avec ça?

Était-ce utile?

La solution

La solution la plus robuste consiste à créer une interface CatalogItem, à créer des wrappers pour chacun de vos services Web et à masquer le tout derrière une usine. L’usine contiendra la logique permettant d’appeler le "correct" Le service Web et le code client devront être modifiés pour utiliser l'interface, mais c'est un changement pour le mieux.

La WCF résout la plupart de ces problèmes avec les contrats de service et si mon avis précédent s'avérait trop ingérable, vous pourriez envisager de migrer vers une solution WCF.

Autres conseils

Je pense que vous allez dans la bonne direction pour cette situation, il va falloir beaucoup de travail pour la ramener à la maison. Je créerais des classes proxy pouvant envelopper les deux versions à l'aide de méthodes de réflexion ou dynamiques. J'ai également vu des personnes utiliser les classes proxy de l'espace de noms distant pour intercepter les appels de méthodes au moment de l'exécution et les diriger au bon endroit. Ainsi, vous pouvez créer les méthodes dynamiques à la demande au lieu de les coder à la main, tout ce dont vous avez besoin pour cela. est une interface qui correspond à l'interface de l'objet.

Ajoutez la référence dont il a besoin ou construisez des wrappers pour CatalogItem et le reste des classes spécifiques. Je construirais les wrappers, l'interface devrait pouvoir fonctionner de manière autonome sans faire référence à une implémentation particulière.

Si les services Web résident dans des espaces de noms différents, il n'y a pas de solution simple (par exemple, quelque chose d'aussi simple que de changer l'URL). Vous semblez être sur la bonne voie avec l'abstraction cependant.

Toutefois, si vous vous sentez aventureux, vous pouvez modifier vous-même les classes de service Web générées (les fichiers "reference.cs"), puis les ajouter manuellement à votre projet. Commencez par créer une interface commune, puis modifiez les premières lignes du fichier comme suit:

public partial class MyWebService : SoapHttpClientProtocol, IMyWebService

Vous l'utilisez ensuite pour appeler le code:

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

Dans VS2008, si j'essaie d'ajouter une référence de service à un service Web, je vois un bouton avancé. Lorsque vous cliquez dessus, vous avez la possibilité de "réutiliser les types".

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top