Question

Disons que j'ai des interfaces:

public interface IFoo {
  IBar DoesStuff();
}
public interface IBar {
  string Thingo { get; }
}

Je consomme ce code dans toute ma base de code. Le processus IFoo doit être déplacé sur un système différent (une différence entre x64 et x32), c’est la raison pour laquelle nous utilisons WFC. Mon service WCF implémente cette interface. Lorsque je crée la "référence de service" les stubs proxy sont créés mais l'interface est modifiée.

public interface IFoo {
   object DoesStuff();
}   

J'ai essayé de définir IBar / Bar à la fois comme DataService et DataContract sans aucune différence. Est-il possible de générer le code proxy en utilisant mon interface?

Je pense que si des objets fictifs peuvent produire un objet de mon interface à des fins de test, ne devrais-je pas être en mesure de faire en sorte que le service l'honore également? Ou avez-vous fait quelque chose de stupide et de mal?

Était-ce utile?

La solution

IBar doit être concret et constituer un DataContract. WCF ne concerne pas les objets distribués, mais plutôt un moyen de transférer des données et de faire fonctionner des services sur ces données. Vous ne pouvez pas retourner dans WCF un objet ayant un comportement.

Autres conseils

Je ne sais pas si vous avez encore besoin d'une solution. Ci-dessous est ce que je ferais. Le truc ici est de ne pas utiliser la norme " ajouter des références de service " comme de nombreux blogs l'ont suggéré, mais rédigez plutôt votre propre proxy client en utilisant Channel Factory. Dans ce cas, vous pouvez choisir de réutiliser vos interfaces mais de redéfinir les classes concrètes en fonction des besoins. Heureux de préciser si vous avez besoin.

// Service Contract
[ServiceContract(name="a", namespace="b")]
public interface IFoo {
    Bar DoesStuff();
}

// Interface to share
public interface IBar {
    string Thingo { get; }
}

// Server Implementation
public class Bar : IBar
{
    string Thingo { get; set; }
}

// Client Proxy reference IBar interface only but redefine concrete class Bar.
public class Bar : IBar 
{
    public string Thingo
    {
        get { return _thingo; }
        set { _thingo = value; }
    }
    string _thingo;
}


/// Sample channel factory implementation
using System;
using System.Configuration;
using System.ServiceModel;
using System.ServiceModel.Channels;

public abstract partial class ServiceProxyBase<TServiceContract> : IServiceProxy
    where TServiceContract : class 
{
    protected ServiceProxyBase()
        : this(null, null)
    {
    }

    protected ServiceProxyBase(string url, Binding binding)
    {
        var contractName = typeof(TServiceContract).Name;
        var urlConfiguration = string.Format("{0}_Url", contractName);
        var serviceUrl = url ?? ConfigurationManager.AppSettings.ValueOrDefault          (urlConfiguration, string.Empty, true);
        if (serviceUrl.IsNullOrEmptỵ̣())
        {
            throw new Exception(string.Format("Unable to read configuration '{0}'", urlConfiguration));
        }

        var serviceBinding = binding ?? new BasicHttpBinding();
        Factory = new ChannelFactory<TServiceContract>(serviceBinding);

        var serviceUri = new Uri(serviceUrl);

        var endPoint = new EndpointAddress(serviceUri);

        Channel = Factory.CreateChannel(endPoint);
    }

    public virtual void Abort()
    {
        isAborted = true;
    }

    public virtual void Close()
    {
        if (Channel != null)
        {
            ((IClientChannel)Channel).Close();
        }

        if (Factory != null)
        {
            Factory.Close();
        }
    }

    private ChannelFactory<TServiceContract> Factory { get; set; }

    protected TServiceContract Channel { get; set; }

    private bool isAborted = false;
}


public class FooServiceProxy : ServiceProxyBase<IFooServiceProxy>, IFooServiceProxy
{
    public Task<Bar> DoesStuffAsync()
    {
        return Channel.DoesStuffAsync();
    }
}

[ServiceContract(name="a", namespace="b")] // The trick when redefine service contract
public interface IFooServiceProxy
{
    [OperationContract]
    Task<Bar> DoesStuffAsync();
}

Essayez de penser aux services Web comme étant multiplates-formes. Que ferait un client Java avec votre interface si vous la renvoyiez?

Oui. Vous devez référencer le projet contenant l'interface avant d'ajouter la référence de service. Ensuite, l'interface sera réutilisée. Il en ira de même pour toutes les classes personnalisées utilisées. Si le projet contenant leurs définitions est référencé par le projet client avant que la référence de service ne soit ajoutée, WCF peut alors réutiliser ces définitions.

Vous devez également accéder à l'onglet Avancé de la boîte de dialogue Ajouter une référence de service et cocher la case "Réutiliser les types dans les assemblages référencés". pour que cela fonctionne.

Une autre façon de peler le chat. Dominic l'a fait en utilisant des attributs KnownType. Découvrez son blog ci-dessous.

http://blogs.msdn.com/b/domgreen/archive/2009/04/13/wcf-using-interfaces-in-method-signatures.aspx

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