WCF DataContract如何在派生类中排除DataMember序列化?

8

我有一个包含DataMember属性的基类,还有一个包含DataMember属性的派生类。在我的WCF项目中,我返回了派生类。有没有办法防止我的基类中的成员被序列化?下面是一些示例代码:

public class BaseClass
{
    public string ShortDescription {get;set;}
    public string LongDescription {get;set;}
}

public class DerivedClass : BaseClass
{
    public List<Description> Descriptions {get;set;}
}

在这段代码中,我希望能够隐藏继承的成员ShortDescription和LongDescription,因为它们现在已经过时。然而,我的所有尝试都没有成功。以下是我尝试过的方法:
public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}

    // override the base class members
    [IgnoreDataMember]    
    public override string ShortDescription {get;set;}
    [IgnoreDataMember]
    public override string LongDescription {get;set;}
}

并且

public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}

    // shadow the base class members
    [IgnoreDataMember]    
    public new string ShortDescription {get;set;}
    [IgnoreDataMember]
    public new string LongDescription {get;set;}
}

这些方法都不起作用。当输出到WSDL时,“DerivedClass”类型仍包含基类类型的“Ignored”成员。

你可能会想为什么我不改变基类。这是因为我仍然使用基类以其原始形式作为WSDL的先前版本,以支持消费者的向后兼容性。通过这种方式,我可以拥有一个返回BaseClass的v1000调用和一个返回DerivedClass的V1010调用。我可以添加和更改DerivedClass的功能而不会影响v1000功能的消费者。

3个回答

7

尝试在两个类上添加[DataContract]属性。这将告诉序列化程序查看[DataMember]和[IgnoreDataMember]属性。如果没有使用[DataContract]对类进行注释,则所有公共成员都会被序列化。

[DataContract]
public class BaseClass
{
    [IgnoreDataMember]
    public string ShortDescription {get;set;}

    [IgnoreDataMember]
    public string LongDescription {get;set;}
}

[DataContract]
public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}
}

另外,如果在[DataContract(Namespace="...")]属性中指定命名空间来为您的数据契约添加命名空间,那将更好。这将会使旧客户端调用您更新后的服务时出现错误。


值得注意的是,在类上使用[DataContract]后,您不再需要显式使用[IgnoreDataMember] - 因为只有带有[DataMember]的成员才会被包含在传输中。 - Ricibob

2

最终我找到了一个合适的方法来处理这个任务。因为我没有代码在手,所以我将根据语法进行推测。这是一个非常简单的解决方案,但它解决了我遇到的特定问题。

public class BaseClass
{
    // leave this guy empty
}

public class DerivedClassVersion1 : BaseClass
{
    [DataMember]
    public string ShortDescription {get;set;}

    [DataMember]
    public string LongDescription {get;set;}
}

public class DerivedClassVersion2 : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}
}

巴达庆!非常简单,但这就是我需要的。

但这不是一个令人满意的答案!现在,您无法使用List<BaseClass>并在列表成员上调用.ShortDescription,因为您的基类中没有ShortDescription;您将不得不在代码中进行强制转换以获取这些描述。 - Chuck

0

试试这个:

public class BaseClass
{
    [DataMember]
    public virtual string ShortDescription {get;set;}

    [DataMember]
    public virtual string LongDescription {get;set;}
}

public class DerivedClass : BaseClass
{
    [DataMember]
    public List<Description> Descriptions {get;set;}

    public override string ShortDescription {get;set;}
    public override string LongDescription {get;set;}
}

编辑:也许利用消息契约来精确控制序列化会起作用:http://msdn.microsoft.com/en-us/library/ms730255.aspx

否则,您还可以考虑实现“WCF路由器”,这将允许您使用相同的终结点,但将不同版本路由到不同的服务。


1
这将产生相同的结果。有趣的是,如果我重写并提供[DataMember]属性以尝试在XML定义中显示DerivedClass,它仍然不会显示在DerivedClass中,而是在基类中显示。 - omatase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接