tags:

views:

302

answers:

1

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?

+3  A: 

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;
    }
}
Darin Dimitrov
i'm sorry i'm pretty wick in wcf, how do i make this on entire service an not per method?
Chen Kinnrot
By implementing IServiceBehavior (http://msdn.microsoft.com/en-us/library/system.servicemodel.description.iservicebehavior.aspx) instead of IOperationBehavior
Darin Dimitrov
you saved me... thanks so much.
What can i do if this is not working for me?
Chen Kinnrot