Chen Kinnrot
Chen Kinnrot

Reputation: 21015

wcf Service Known type attribute question

i wanna add a service behavior(or anything u'll suggest) that will automatically insert the types from dll to the service known types of the service

is it possible? how?

Upvotes: 3

Views: 2698

Answers (1)

Darin Dimitrov
Darin Dimitrov

Reputation: 1038730

Known type attributes are passed to the DataContractSerializer constructor. You can customize the way this serializer is instantiated and provide the known types to the constructor of the serializer by reflecting over your assemblies and finding all types that derive from a base class.

Here's a sample code (not tested):

[ServiceContract]
public interface FooContract
{
    [OperationContract]
    [KnownTypesDataContractFormat(typeof(SomeBaseType))]
    void MyOperation(SomeBaseType arg);
}

public class KnownTypesDataContractFormatAttribute : Attribute, IOperationBehavior
{
    public Type BaseType { get; private set; }
    public KnownTypesDataContractFormatAttribute(Type baseType)
    {
        BaseType = baseType;
    }

    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    { }

    public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
    {
        IOperationBehavior innerBehavior = new KnownTypesDataContractSerializerOperationBehavior(description, BaseType);
        innerBehavior.ApplyClientBehavior(description, proxy);
    }


    public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
    {
        IOperationBehavior innerBehavior = new KnownTypesDataContractSerializerOperationBehavior(description, BaseType);
        innerBehavior.ApplyDispatchBehavior(description, dispatch);
    }

    public void Validate(OperationDescription description)
    { }
}

public class KnownTypesDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
    public Type BaseType { get; private set; }
    public KnownTypesDataContractSerializerOperationBehavior(OperationDescription operationDescription, Type baseType) : base(operationDescription) 
    {
        BaseType = baseType;
    }

    public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
    {
        return new DataContractSerializer(type, name, ns, knownTypes);
    }

    public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
    {
        return new DataContractSerializer(type, name, ns, knownTypes);
    }

    private IEnumerable<Type> GetKnownTypes()
    {
        // Try to find all types that derive from BaseType in the 
        // executing assembly and add them to the knownTypes collection
        return 
            from type in Assembly.GetExecutingAssembly().GetTypes()
            where type != BaseType && BaseType.IsAssignableFrom(type)
            select type;
    }
}

Upvotes: 7

Related Questions