Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to mark an interface as DataContract in WCF


i have two data classes which hold only data members(no functions). One is CallTask the other is SmsTask. These two classes have some common properties like ID, Tel. I put these common properties in a seperate interface class and i use this interface class in my project whenever appropriate.
Now i added a WCFService to my project to share data between clients and server. Consider the following class design:

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

in this design, i want to host CallTask, SmsTask, and IGsmTask to the clients to use these in service methots like the following;

    [OperationContract]
    public void AddTask(IGsmTask task)
    {

    }

i tried to mark [DataContract] on IGsmTask but it gives me complition error. Isnt there any methot that i can use interfaces as DataContracts? Or how should i use KnownAttributes types in this synerio?
Thanks.

like image 286
Fer Avatar asked Apr 02 '12 08:04

Fer


2 Answers

As far as I know using interfaces as datacontracts is not possible. You may use a base class and add knowntype attributes on the otherhand.

like image 92
daryal Avatar answered Oct 19 '22 23:10

daryal


Fer: Everything is Possible with the right design.

If the issue is:

a class is a data contract

&&

1 or more of its properties must be an interface...

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

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

The issue is that when the de-serialization occurs -- There is no way to turn the data into a class that implements ICustomInterface.

The Solution is to create a concrete class that does Implement the interface, and cast the getter/setter of the public property (that is of type interface) into a private property of the concrete class.

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);}
     }
}
like image 29
Zack Weiner Avatar answered Oct 19 '22 22:10

Zack Weiner