freddes.se

…because I'm a nerd

WCF KnownType attribute example

with one comment

In this article I will present an easy to understand example when to use Data Contract Known Types, e.g. the KnownTypeAttribute class, to make a WCF Service serialize and a service consumer deserialize types when using inheritance. The MSDN has the complete documentation on this, take a look here: KnownTypeAttribute Class.

In this example I will use a hierarchy of different types of vehicles, e.g. a base vehicle type, a car type, a bike type and a kid’s bike type. I will use WCF 4 (.NET 4), Visual Studio 2010 and the WcfTestClient to test the service.
The great thing with KnownTypeAttribute is that WCF can expose one method supporting all types in a class in a hierarchy.

Classes to expose

The class hierarchy looks like this:

This is a really simple inheritance model but will still show the concept of using the KnownTypeAttribute class.

Note that the Vehicle class is abstract due to the abstract NoOfWheels property.

The code behind this class diagram looks like this (comments below the code):

using System.Runtime.Serialization;

namespace WcfKnowTypesLab
{
    ///
    /// Base class, abstract
    ///
    [KnownType(typeof(Car))]
    [KnownType(typeof(Bike))]
    abstract public class Vehicle
    {
        public int ID { get; set; }

        abstract public int NoOfWheels { get; }

        public string Brand { get; set; }
    }

    ///
    /// Car class, inherits from Vehicle
    ///
    public class Car : Vehicle
    {
        override public int NoOfWheels { get { return 4; } }

        public string SteeringWheelPosition { get; set; }
    }

    ///
    /// Bike class, inherits from Vehicle
    ///
    [KnownType(typeof(KidsBike))]
    public class Bike : Vehicle
    {
        override public int NoOfWheels { get { return 2; } }

        public bool HasFrontWheelBreak { get; set; }
    }

    ///
    /// Kid's bike class, inherits from Bike
    ///
    public class KidsBike : Bike
    {
        public bool HasSupportingWheels { get; set; }
    }
}

Comments:

  • The DataContract attribute is left out. This will make all public properties implementing both get and set methods to be serialized by WCF.
  • The property NoOfWheels (marked as abstract in the vehicle class) will not be serialized due to the missing set method.
  • The vehicle class has two instances of the KnownType attribute, Car and Bike, that make Car and Bike objects valid as parameter and return value types by WCF.
  • The bike class have a KnownType attribute pointing out the KidsBike class, that makes the KidsBike object valid as parameter and return value type by WCF.

Above the usage of the KnownType attribute is shown. Let’s take a look at the service interface and the implementation. The WcfTestClient is used below to test the service.

The service interface

The service will expose two methods, one returning a Vehicle and one taking a Vehicle as parameter. The interface exposed by the service looks like this:

using System.ServiceModel;

namespace WcfKnowTypesLab
{
    [ServiceContract]
    public interface IVehicleService
    {
        [OperationContract]
        Vehicle GetVehicle(int type);

        [OperationContract]
        int GetNumberOfWheels(Vehicle vehicle);
    }
}

The GetVehicle function need an integer parameter to decide the type of vehicle to return (see the code for the implementation of  the interface below).

The GetNumberOfWheels returns the number of wheels of the vehicle passed as parameter (the number of wheels property will not be serialized since it doesn’t implement any set method, see code below).

The implementation of the interface looks like this:

namespace WcfKnowTypesLab
{
    public class VehicleService : IVehicleService
    {
        public Vehicle GetVehicle(int type)
        {
            switch (type)
            {
                case 0:
                    return new Car()
                    {
                        ID = 10,
                        Brand = "Volvo",
                        SteeringWheelPosition = "left"
                    };

                case 1:
                    return new Bike()
                    {
                        ID = 11,
                        Brand = "Scott",
                        HasFrontWheelBreak = true
                    };

                case 2:
                    return new KidsBike()
                    {
                        ID = 12,
                        Brand = "Kid Scott",
                        HasFrontWheelBreak = false,
                        HasSupportingWheels = true
                    };

                default:
                    return null;
            }
        }

        public int GetNumberOfWheels(Vehicle vehicle)
        {
            return vehicle.NoOfWheels;
        }
    }
}

The to functions above is straight forward, but let’s make a couple of comments anyway:

  • The GetVehicle function will return an object of a certain type, based on the type parameter:
    • 0: A Car object is returned
    • 1: A Bike object is returned
    • 2: A KidsBike object is returned
    • null otherwise
  • The different types of vehicles returned are valid Vehicle type objects and they will be serialized correctly because of the KnownType attribute shown above.
  • The GetNumberOfWheels function will return the number of wheels (more or less constant, depending on the subclass object passed as parameter). Take a closer look at the NumberOfWheels property for the classes shown above.

Service testing

First I will show the results of invoking the GetVehicle function, with all the valid type parameter values.

GetVehicle(0):

GetVehicle(1):

GetVehicle(2):

GetVehicle(<some value causing null to be returned, e.g. 99):

The above screenshots of the WcfTestClient show the different types of objects returned by the service, depending on the type parameter passed to the service function.

Let’s take a look at the GetNumberOfWheels function. I will pass a Car and a KidsBike object as parameters

GetNumberOfWheels(<a Car object>):

GetNumberOfWheels(<a KidsBike object>):

Note that an object of type Vehicle may not be returned or passed as parameter since it is abstract. A subclass needs to implement the abstract stuff in such a class.

These screenshots showing the results from the different functions exposed by the service ends this article. Isn’t the KnownType attribute a nice feature? I like it very much!

Written by Fredde

May 19th, 2010 at 11:37 pm

Posted in .NET,C#,WCF

Tagged with , , ,

One Response to 'WCF KnownType attribute example'

Subscribe to comments with RSS or TrackBack to 'WCF KnownType attribute example'.

  1. This was very helpful – thanks for writing this!

    rh

    29 Jul 10 at 17:49

Leave a Reply