您可以使用以下 DataContractResolver 扩展 [DataContract(Name = "Base")] 作为 Derived 上的属性的使用,以指定它应该序列化为 Base 以在服务器接口方法返回接口而不是具体基类型的情况下工作.
要使用它,Base 必须声明为 KnownType (ServerKnownType),Derived 必须具有 [DataContract(Name = "Base")] 属性,但不能声明为 KnownType。
public class DeserializeAsBaseResolver : DataContractResolver {
public static void Install(ServiceHost serviceHost) {
SetSerializationBehavior(serviceHost, "MethodReturningIInterfac");
}
public static void SetSerializationBehavior(ServiceHost serviceHost, string contractMethodName) {
ContractDescription cd = serviceHost.Description.Endpoints[0].Contract;
OperationDescription myOperationDescription = cd.Operations.Find(contractMethodName);
bool methodFound = (myOperationDescription != null);
if (!methodFound) {
string msg = string.Format("\"{0}\" not a valid method on {1}",
contractMethodName, cd.ConfigurationName);
throw new ArgumentException(msg);
}
DataContractSerializerOperationBehavior serializerBehavior =
myOperationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (serializerBehavior == null) {
serializerBehavior = new DataContractSerializerOperationBehavior(myOperationDescription);
myOperationDescription.Behaviors.Add(serializerBehavior);
}
serializerBehavior.DataContractResolver = new DeserializeAsBaseResolver();
}
public override bool TryResolveType(Type type, Type declaredType,
DataContractResolver knownTypeResolver,
out XmlDictionaryString typeName,
out XmlDictionaryString typeNamespace) {
// Look for [DataContract(Name = "ClassType")] attribute and serialize as that
// type if one is found:
Type typeToResolveOn = type;
DataContractAttribute dca = null;
// .Net 4.0 and below code:
object[] attributes = type.GetCustomAttributes(typeof(DataContractAttribute), false);
foreach (object attibute in attributes) {
if (attibute is DataContractAttribute) {
dca = attibute as DataContractAttribute;
break;
}
}
// .Net 4.5 and above code:
//dca = type.GetCustomAttribute<DataContractAttribute>();
if (dca != null && !string.IsNullOrEmpty(dca.Name)) {
string modifiedAssemblyQualifiedName = string.Format("{0}.{1}, {2}", type.Namespace, dca.Name, type.Assembly);
Type serializeAsType = Type.GetType(modifiedAssemblyQualifiedName);
if (serializeAsType != null)
typeToResolveOn = serializeAsType;
}
bool ret = knownTypeResolver.TryResolveType(typeToResolveOn, declaredType, null, out typeName, out typeNamespace);
if (!ret && type != typeToResolveOn)
ret = knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace);
return ret;
}
public override Type ResolveName(string typeName, string typeNamespace,
Type declaredType, DataContractResolver knownTypeResolver) {
return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? declaredType;
}
}
}