SF Developer
SF Developer

Reputation: 5384

C# - WCF - Generics - [KnownType(typeof(xxx))]

My client has 10 tables that it needs to load via an internal WCF to a server. Since all this is internal, I can write both client and server using whatever technique i want.

On the Client, I thought to use LINQ to load data from the tables to a List, List and so on...

On the Server, I thought to have a [DataContract] as follow:

[DataContract]
[KnownType(typeof(Table1))]
[KnownType(typeof(Table2))]
[KnownType(typeof(Table3))]
public class GenericType<T>
{
    [DataMember]
    public List<T> Data { get; set; }
}

and then add the classes that will represent the matching Tables on the Client.

[DataContract]
public class Table1
{
    [DataMember]
    public int UserID { get; set; }
    [DataMember]
    public string FullName { get; set; }
}

[DataContract]
public class Table2
{
    [DataMember]
    public int UserID { get; set; }
    [DataMember]
    public string Address1 { get; set; }
}

[DataContract]
public class Table3
{
    [DataMember]
    public string Name { get; set; }
    [DataMember]
    public string Description { get; set; }
}

When I create the client reference, i'm NOT getting all the classes declared on the server and it seems that ONLY the 1st [KnownType] specified on the [DataContract] becomes visible to the Client.

I was under the impression that Generics was meant to allow multiple types but am I right to think that WCF can only handle one [KnownType] x class ??

And if so, my only way to code this would be to copy and paste 10 times the GenericType class and on each copy, change the [KnownType] ??

Cause if that's the only solution, then what are the real benefits to use Generic instead of straight defined List, List for my params ??

Any thought will help clarify my mind here


The problem happens because unless ONE of the WCF methods uses any of the CLASSES declared as [DataContract] ...it seems that WCF does NOT brings those classes to the Client.

Is this the expected case?

Upvotes: 1

Views: 2204

Answers (1)

competent_tech
competent_tech

Reputation: 44971

You could try attributing your interface method with the ServiceKnownType attribute for each of the classes.

There is another option, which is to implement the generic lists in classes that are attributed with CollectionDataContract:

[CollectionDataContract]
public class Table1Collection
   Inherits List<Table1>

On the client side, you can the edit Reference.svcmap and enumerate each of the collections in the CollectionMappings section:

<CollectionMappings>
  <CollectionMapping TypeName="My.Namespace.Table1Collection" Category="List" />

This allows you to reuse the same code on both ends of the pipe.

Upvotes: 1

Related Questions