Атрибуты известного типа передаются в конструктор DataContractSerializer. Вы можете настроить способ создания экземпляра этого сериализатора и предоставить известные типы для конструктора сериализатора, отражая ваши сборки и находя все типы, производные от базового класса. *
Вот пример кода (не тестировался):
[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;
}
}