Domanda

Diciamo che ho alcune interfacce:

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

Sto consumando questo codice in tutta la mia base di codice. Il processo IFoo deve essere spostato su un sistema diverso (una differenza di x64 vs x32), questa è la nostra ragione per usare WFC. Il mio servizio WCF implementa questa interfaccia. Quando creo il "servizio di riferimento" " gli stub proxy vengono creati ma l'interfaccia viene modificata.

public interface IFoo {
   object DoesStuff();
}   

Ho provato a definire IBar / Bar come DataService e DataContract senza alcuna differenza. C'è un modo per generare il codice proxy usando la mia interfaccia?

Sto pensando se gli oggetti finti possono produrre un oggetto della mia interfaccia per i test, quindi non dovrei essere in grado di ottenere anche il servizio per onorarlo? O ha fatto qualcosa di sciocco e sbagliato?

È stato utile?

Soluzione

IBar deve essere concreto e un DataContract. WCF non riguarda gli oggetti distribuiti, ma piuttosto un modo per trasferire dati e far funzionare i servizi su tali dati. Non è possibile restituire un oggetto in WCF con comportamento.

Altri suggerimenti

Non so se hai ancora bisogno di una soluzione. Di seguito è quello che farei. Il trucco qui non è usare lo standard "aggiungi riferimenti di servizio" come molti blog hanno suggerito, ma piuttosto scrivere il proprio proxy client utilizzando Channel Factory. In questo caso, puoi scegliere di riutilizzare le tue interfacce ma ridefinire le classi concrete come richiesto. Felice di elaborare ulteriormente se è necessario.

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

Prova a pensare ai servizi web come multipiattaforma. Cosa farebbe un client Java con la tua interfaccia se lo restituissi?

Sì. È necessario fare riferimento al progetto contenente l'interfaccia prima di aggiungere il riferimento al servizio. Quindi l'interfaccia verrà riutilizzata. Lo stesso vale per qualsiasi classe personalizzata utilizzata: se il progetto contenente le loro definizioni viene referenziato dal progetto client prima dell'aggiunta del riferimento al servizio, WCF può riutilizzare tali definizioni.

Dovrai anche andare alla scheda Avanzate nella finestra di dialogo Aggiungi riferimento al servizio e spuntare " Riutilizzare i tipi negli assiemi referenziati " per farlo funzionare.

Un altro modo di scuoiare il gatto. Dominic l'ha fatto usando gli attributi KnownType. Dai un'occhiata al suo blog qui sotto.

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top