2009-02-04 18 views
24

In un servizio WCF, ho due classi con l'attributo [DataContract]. Una di queste classi ha una relazione "is-a" con l'altra - quindi la classe B può ereditare dalla classe A. Tuttavia, quando configuro l'ereditarietà tra queste due classi, entrambe con un attributo [DataContract], i metadati non vengono caricati durante il test dei servizi.In WCF, le classi di contratto dati possono ereditare l'una dall'altra?

È possibile in WCF? Mi manca un altro attributo?

[DataContract] 
public class A 
{   
    [DataMember] 
    public MyCustomType AValue1{ get; set; } 

    [DataMember] 
    public MyCustomType AValue2 { get; set; } 
} 

[DataContract] 
public class B: A 
{  
    [DataMember] 
    public double BValue1{ get; set; } 

    [DataMember] 
    public double BValue2 { get; set; } 
} 

NOTA: i tipi personalizzati vengono anche definiti mediante contratti di dati.

UPDATE: Di seguito è riportato l'errore:

Error: Cannot obtain Metadata from http://localhost:8002/GISDataServices/mex If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: http://localhost:8002/GISDataServices/mex Metadata contains a reference that cannot be resolved: ' http://localhost:8002/GISDataServices/mex '. Receivera:InternalServiceFault The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.HTTP GET Error URI: http://localhost:8002/GISDataServices/mex There was an error downloading ' http://localhost:8002/GISDataServices/mex '. The request failed with HTTP status 400: Bad Request.

UPDATE 2: Vedere la mia risposta qui sotto.

risposta

38

Sì, ma è necessario decorare la classe base con [KnownTypeAttribute] costruendolo con il tipo della classe derivata. Ad esempio:

[DataContract] 
[KnownType(typeof(B))] 
public class A 
{ 
    [DataMember] 
    public string Value { get; set; } 
} 

[DataContract] 
public class B : A 
{ 
    [DataMember] 
    public string OtherValue { get; set; } 
} 
+0

Questo non sembra funzionare. Ricevo ancora un errore durante il caricamento dei metadati. –

+0

Qual è l'errore che stai vedendo? –

+0

Ottima domanda. Puoi pubblicare il tuo errore esatto? –

1

Sulla base di questo test dovrebbe funzionare correttamente. Entrambe le classi hanno costruttori predefiniti? Stai usando Proprietà automatiche. Nota, in questo campione di base gli attributi non sono richiesti. Inoltre, dato che David Morton ti ha menzionato a seconda dell'elemento che stai restituendo potresti aver bisogno dell'attributo KnownType, non sono al 100% ma il tipo noto potrebbe dover andare sul contratto operativo.

class Program 
{ 
    static void Main(string[] args) 
    { 
     var serializer = new DataContractSerializer(typeof(Employee)); 

     var employee = new Employee() { Name="Joe", Salary=100000 }; 
     using (var ms = new MemoryStream()) 
     { 
      serializer.WriteObject(ms, employee); 

      ms.Position = 0; 

      var newEmployee = serializer.ReadObject(ms) as Employee; 
     } 

     Console.ReadKey(); 

    } 
} 

[DataContract] 
public class Employee : Person 
{ 
    [DataMember] 
    public decimal Salary { get; set; } 
} 

[DataContract] 
public class Person 
{ 
    [DataMember] 
    public string Name { get; set; } 
} 

[ServiceContract] 
interface IEmployeeService 
{ 
    [OperationContract] 
    Person GetPerson(); 

    [OperationContract] 
    Employee GetEmployee(); 

    [OperationContract] 
    [KnownType(typeof(Employee))] 
    Person GetEmployeeAsPerson(); 
} 
+0

sto usando auto-proprietà, ma quelli funzionano bene quando rimuovo il costrutto eredità. –

+0

Nessuna delle due classi utilizza un costruttore esplicito. –

+0

Puoi aggiornare il tuo post con il costrutto di ereditarietà del problema? – bendewey

7

Ok, ho capito la domanda. La risposta è ... sono un idiota. Non aveva niente a che fare con l'ereditarietà. Nella classe base, avevo un membro del contratto dati senza una clausola di proprietà 'set' - solo un 'get'. Doh !!! Mettendo in una clausola 'set' ha funzionato come un fascino.

Ci scusiamo per la confusione.