0

如果 a[ServiceContract] [OperationContract]指定了一个接口 ( IInterface) 的返回值,那么我可以使用服务器接口上的 ServerKnownType 属性 返回一个基对象 ( Base : IInterface) 或一个派生对象 ( )。Derived : Base

但是,如果我需要将 Derived 对象作为 Base 对象传输(因为 Derived 添加了服务器端功能,我不需要客户端),那么我就卡住了。Derived 类技巧(请参阅此处
)在 这种情况下(服务器方法返回接口)不起作用,因为我们必须将 Derived 对象和 Base 对象声明为 KnownTypes - 当服务器将类型解析为序列化它不喜欢有 2 个不同的已知类型具有相同的数据合同名称 - 并且在解析时会抛出异常。在这种情况下如何将 Derived 作为 Base 传输?[DataContract(Name = "Base")]

4

1 回答 1

0

您可以使用以下 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;
        }
    }

}
于 2013-04-12T09:49:52.733 回答