Registering WCF Service Known Types at Runtime

I am working on a number of WCF services which will be accessed over named pipes (for the first release anyway) and be consumed by a number of internal applications.  The operations on the services process graphs  of Data Transfer Objects (DTOs).  Both the request and the response of the operation may involve either a shallow or a deep graph of objects from my library of (currently) forty types.  For these services to work, not only do I need to ensure that each DTO is marked up with the appropriate DataContract and DataMember attributes, but also I need to register each of the forty types for each of WCF services.  Now I could do this:

      [ServiceKnownType(typeof(Type1))]
    ...
    [ServiceKnownType(typeof(Type40))]  
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        OperationResponse DoSomething(OperationRequest request);
    }

But clearly, this violates the DRY principle.  And every time I add a new DTO, as I presume I will need to do for subsequent releases, I will need to remember to add the new type to the list of service known types in each of my WCF service definitions.

Instead, I have opted for the following approach:

      [ServiceContract]
    public interface IService
    {
        [OperationContract]
        [ServiceKnownType("ListKnownTypes", typeof(KnownTypesRegister))]
        OperationResponse DoSomething(OperationRequest request);
    }

    static class KnownTypesRegister
    {
        public static IEnumerable ListKnownTypes(ICustomAttributeProvider provider)
        {
            Assembly dtoDefinitions = Assembly.Load("assemblyname, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
            var query = from t in dtoDefinitions.GetTypes() where t.IsClass && t.Namespace == "namespace" select t;
            return query.ToList();            
        }
    }


With essentially only three lines of code I have a much more extensible solution, far less prone to defect injection during maintenance and subsequent releases.

Comments