如何在WCF中将接口标记为DataContract

15


我有两个数据类,它们只包含一些数据成员(没有函数)。一个是CallTask,另一个是SmsTask。这两个类有一些共同的属性,如IDTel。我将这些公共属性放在一个单独的接口类中,并在项目中适当的时候使用该接口类。
现在,我添加了一个WCF服务到我的项目中,以便在客户端和服务器之间共享数据。考虑以下类设计:

public interface IGsmTask : IComparable
{
    string TaskID { get; set; }
    string SessionID { get; set; }
    string Tel { get; set; }
}

class CallTask : IGsmTask
{
    #region IGsmTask Members

    public string TaskID { get; set; }

    public string SessionID { get; set; }

    public string Tel { get; set; }

    #endregion        
}

class SmsTask : IGsmTask
{
    #region IGsmTask Members

    public string TaskID { get; set; }

    public string SessionID { get; set; }

    public string Tel { get; set; }

    #endregion

    public string SmsText { get; set; }
}
在这个设计中,我希望将CallTask、SmsTask和IGsmTask托管给客户端,在服务方法中使用它们,如下所示:
    [OperationContract]
    public void AddTask(IGsmTask task)
    {

    }

我尝试在IGsmTask上标记[DataContract],但它给我带来了编译错误。是否有一种方法可以将接口用作DataContract?或者在这种情况下应该如何使用KnownAttributes类型?
谢谢。


谢谢Reniuz,看起来我不能使用接口来实现这个目的。 - Fer
2
WCF是一种基于消息的系统 - 客户端向服务器发送XML序列化消息。因此,这些消息必须是可以序列化为XML并用XML模式表示的具体类型。接口无法序列化为XML... - marc_s
1
首先,我会创建一个类来存储公共属性,而不是接口。这样可以在每个派生类中至少节省3行代码。 - Renatas M.
2个回答

13
据我所知,使用接口作为数据契约是不可能的。相反,您可以使用基类并在另一方面添加knownType属性。

我以为可以使用接口作为数据契约的方法。如果不可能,我将不得不将我的接口更改为基类。谢谢。 - Fer
1
由于序列化是基于对象实例的,我认为没有直接的方法来完成它。 - daryal

10

Fer: 有了正确的设计,一切皆有可能。

如果问题是:

一个类是数据契约

&&

其中一个或多个属性必须是接口…

public interface ICustomInterface
{
    int Property1 {get;set}
}

[DataContract]
public class MyClass
{
     [DataMember(Name="_myInterface")]
     public ICustomInterface MyInterface {get;set;}
}

问题在于当反序列化发生时,没有办法将数据转换为实现了ICustomInterface接口的类。

解决方案是创建一个具体的类来实现该接口,并将公共属性(类型为接口)的getter/setter转换为具体类的私有属性。

public class CustomInterfaceImplementor: ICustomInterface
{
     public int Property1 {get;set;}
}

[DataContract]
public class MyClass
{
     [DataMember(Name="_myInterface")]
     private CustomInterfaceImplementor _MyInterface;
     public ICustomInterface MyInterface
     {
          get {return (_MyInterface as ICustomInterface);}
          set {_MyInterface = (value as CustomInterfaceImplementor);}
     }
}

创建一个新类意味着所有内容都必须重新初始化,如果您只想省略一些属性,这将是一件麻烦事。我认为这是又一种语言限制。 - symbiont
似乎只需使用以下代码即可正常工作:get { return _MyInterface; } set { _MyInterface = value; } 因此,您可以省略 "as"。 - RWC

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