在WCF中,数据契约类可以相互继承吗?

时间:2022-09-25 11:59:15

In a WCF service, I have two classes with the [DataContract] attribute. One of these classes has an "is-a" relationship with the other - so class B can inherit from class A. However, when I configure inheritance between these two classes, both denoted with a [DataContract] attribute, the metadata fails to load when testing the services.

在WCF服务中,我有两个具有[DataContract]属性的类。其中一个类与另一个类具有“is-a”关系 - 因此类B可以从类A继承。但是,当我在这两个类之间配置继承时,两者都用[DataContract]属性表示,元数据无法加载在测试服务时。

Is this possible in WCF? Am I missing another attribute?

这可能在WCF中吗?我错过了另一个属性吗?

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

NOTE: The custom types are also defined using data contracts.

注意:还使用数据协定定义自定义类型。

UPDATE: Below is the error:

更新:以下是错误:

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:InternalServiceFaultThe 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.

错误:无法从http:// localhost:8002 / GISDataServices / mex获取元数据如果这是您有权访问的Windows(R)Communication Foundation服务,请检查您是否已在指定地址启用元数据发布。有关启用元数据发布的帮助,请参阅http://go.microsoft.com/fwlink/?LinkId=65455上的MSDN文档.WS-Metadata Exchange错误URI:http:// localhost:8002 / GISDataServices / mex元数据包含无法解析的引用:'http:// localhost:8002 / GISDataServices / mex'。 Receivera:InternalServiceFault由于内部错误,服务器无法处理请求。有关错误的更多信息,请在服务器上启用IncludeExceptionDetailInFaults(来自ServiceBehaviorAttribute或来自 配置行为),以便将异常信息发送回客户端,或者根据Microsoft .NET Framework打开跟踪3.0 SDK文档并检查服务器跟踪日志.HTTP GET错误URI:http:// localhost:8002 / GISDataServices / mex下载'http:// localhost:8002 / GISDataServices / mex'时出错。请求失败,HTTP状态为400:错误请求。

UPDATE 2: See my answer below.

更新2:请参阅下面的答案。

3 个解决方案

#1


39  

Yes, but you need to decorate the base class with the [KnownTypeAttribute] constructing it with the derived class's type. For instance:

是的,但您需要使用[KnownTypeAttribute]使用派生类的类型构造它来装饰基类。例如:

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

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

#2


7  

Okay, I figured out the question. The answer is...I'm an idiot. It had nothing to do with inheritance. In the base class, I had a data contract member without a 'set' property clause - only a 'get'. Doh!!! Putting in a 'set' clause made it work like a charm.

好的,我想出了这个问题。答案是......我是个白痴。它与继承无关。在基类中,我有一个没有'set'属性子句的数据契约成员 - 只有'get'。卫生署!加入'set'条款使它像魅力一样工作。

Sorry for the confusion.

对困惑感到抱歉。

#3


1  

Based on this test it should work fine. Do both classes have Default Constructors? Are you using Auto-Properties. Note, In this basic sample the Attributes aren't required. Also, as David Morton mentioned you depending on which element you're returning you may need the KnownType attribute, I'm not 100% but the known type might have to go on the operation contract.

根据这个测试,它应该工作正常。这两个类都有默认构造函数吗?您使用的是自动属性吗?注意,在此基本示例中,不需要属性。另外,正如David Morton根据您返回的元素提到的那样,您可能需要KnownType属性,我不是100%,但已知类型可能需要继续操作合同。

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

#1


39  

Yes, but you need to decorate the base class with the [KnownTypeAttribute] constructing it with the derived class's type. For instance:

是的,但您需要使用[KnownTypeAttribute]使用派生类的类型构造它来装饰基类。例如:

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

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

#2


7  

Okay, I figured out the question. The answer is...I'm an idiot. It had nothing to do with inheritance. In the base class, I had a data contract member without a 'set' property clause - only a 'get'. Doh!!! Putting in a 'set' clause made it work like a charm.

好的,我想出了这个问题。答案是......我是个白痴。它与继承无关。在基类中,我有一个没有'set'属性子句的数据契约成员 - 只有'get'。卫生署!加入'set'条款使它像魅力一样工作。

Sorry for the confusion.

对困惑感到抱歉。

#3


1  

Based on this test it should work fine. Do both classes have Default Constructors? Are you using Auto-Properties. Note, In this basic sample the Attributes aren't required. Also, as David Morton mentioned you depending on which element you're returning you may need the KnownType attribute, I'm not 100% but the known type might have to go on the operation contract.

根据这个测试,它应该工作正常。这两个类都有默认构造函数吗?您使用的是自动属性吗?注意,在此基本示例中,不需要属性。另外,正如David Morton根据您返回的元素提到的那样,您可能需要KnownType属性,我不是100%,但已知类型可能需要继续操作合同。

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