在WCF中,数据协定类可以相互继承吗?

时间:2009-02-04 15:19:38

标签: .net wcf contract

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

这可能在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; }
}

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

更新:以下是错误:

  

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

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

3 个答案:

答案 0 :(得分:39)

是的,但您需要使用[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; }
}

答案 1 :(得分:7)

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

很抱歉这个混乱。

答案 2 :(得分:1)

根据此测试,它应该可以正常工作。这两个类都有默认构造函数吗?您使用的是自动属性吗?注意,在此基本示例中,不需要属性。另外,正如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();
}