Domanda

Sono un principiante in WCF, attualmente sto sviluppando un servizio TCP WCF e non sono sicuro di aver compreso correttamente il passaggio dei parametri, quindi vi consiglio di commentare e fornire un modo standardizzato.

Per chiarire le cose, ho sviluppato un piccolo servizio a scopo di test che ha un metodo singolo e dipende da una DLL .Net esterna che espone una singola classe. Il codice del contratto di servizio

    [ServiceContract]
    public  interface IMyService
    {
        [OperationContract]
        int Test1(actionType at, calculationType ct, action a);
        [OperationContract]
        int Test2(DataSeries s);
    }

Dove actionType , calcoloType , azione sono enumerati all'interno della dll esterna e DataSeries è una classe dichiarata all'interno della dll.

La definizione originale per la classe DataSeries nella dll è contrassegnata solo da [Serializable] e non [DataMember] sui suoi membri.

Sto usando la terza dll sul lato client e server, la mia sorpresa è stata che entrambe le applicazioni funzionavano bene senza mettere [DataContract] sulla classe DataSeries e senza usare nessuno di [EnumMember] dentro enums, [DataMember] all'interno della classe.

Quindi cosa sta succedendo?

Un altro esperimento:

Rimozione della terza parte dal lato client e utilizzo del servizio così com'è Ho scoperto che vs2008 genera gli enum e la classe DataSeries e li contrassegna con gli attributi corretti? come

    [System.CodeDom.Compiler.GeneratedCodeAttribute      ("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute(Name="actionType",  Namespace="http://schemas.datacontract.org/2004/07/DBInterface")]
    public enum actionType : int {

        [System.Runtime.Serialization.EnumMemberAttribute()]
        All = 0,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Buy = 1,

        [System.Runtime.Serialization.EnumMemberAttribute()]
        Sell = 2,
    }
È stato utile?

Soluzione

DataContract , DataMember e EnumMember sono usati dagli attributi DataContractSerializer (in genere basicHttpBinding o wsHttpBinding ). Se si sta esponendo un endpoint con associazione TCP ( netTcpBinding ) è richiesto solo SerializableAttribute . Nota che con DataContractSerializer potresti solo aggiungere SerializableAttribute alle tue classi e serializzerà automaticamente tutti i campi.

Ti consiglierei quanto segue: se vuoi che il tuo servizio sia interoperabile, usa basicHttpBinding e contrassegna le tue classi con gli attributi DataContract e DataMember. Se il tuo client è un'applicazione .NET, usa netTcpBinding e contrassegna le tue classi con SerializableAttribute.

Puoi anche leggere questo post per un confronto tra attacchi diversi.

Altri suggerimenti

  

Ma senza usare DataContract o nessuno   attributi, ho trovato il lato client   funziona correttamente

Sì, è vero - se i tipi di dati che usi non sono contrassegnati con [DataContract], WCF proverà a utilizzare il serializzatore SOAP predefinito su di essi e serializzerà tutto ciò che è pubblico (tutte le proprietà pubbliche).

Funziona - ma potrebbe non essere quello che vuoi / ti aspetti - quindi secondo l'opinione di darin - uso sempre gli attributi espliciti [DataContract] sui tuoi tipi. Più chiaro fai le tue intenzioni a te stesso (o ad altri programmatori che devono mantenere il tuo codice in un secondo momento), meglio è. Questi "trucchi magici" che accadono dietro le quinte tendono a creare confusione a volte - è meglio che non faccia troppo affidamento su di loro

Marc

Quindi per me uso [DataContract] s, passo un singolo parametro e restituisco un contratto dati.

Ciò offre maggiore flessibilità, poiché posso estendere il contratto dati con nuovi attributi opzionali al contratto dati, senza interrompere alcun cliente esistente.

Enum per cui creo anche i Contatti dati; perché posso quindi fare lo stesso, estendendo l'enum senza rompere nulla e posso controllare lo spazio dei nomi.

[DataContract(Namespace = "http://namespace.mydomain.com/2009/05", Name = "ReferenceTypeData")]
public enum GenderEnum
{
    [EnumMember()]
    Unknown = 0,
    [EnumMember()]
    Male = 1,
    [EnumMember()]
    Female = 2
}

È quindi necessario contrassegnare il contratto di servizio con

[ServiceKnownType(typeof(GenderEnum))]
public interface IServiceContract
{
    ....
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top