我从客户端将对象传输到WCF服务时遇到问题。我无法使用标准合约定义,因为它是几个不同应用程序的通用服务。
服务器和客户端都有一个程序集,其中定义了传输类型,因此服务器可以从SOAP消息反序列化对象实例。首先,我尝试“按原样”发送此对象,但得到了关于未预期的合同名称的消息:“类型'类型名称'与数据合同名称'X:Y'不是预期的。考虑使用DataContractResolver或添加任何未知的类型静态地到已知类型的列表 - 例如,通过使用KnownTypeAttribute属性或将它们添加到传递给DataContractSerializer的已知类型列表。“
经过研究,我了解到有几种方法可以解决这个问题: 1.使用KnownType []属性(这是不可能的,因为我不知道编译时所有类型) 2.使用静态合约(类似) 3.使用DataContractResolver(没关系,因为我可以查看程序集并尝试查找这些类型)
在学习本文之后 - http://code.msdn.microsoft.com/windowsdesktop/WCF-Data-Contract-Resolver-7de9b8b4#content - 我创建了一个属性来替换我的项目中的Resolver(因为它是由IIS托管的):
public class DataContractResolverAttribute: Attribute, IOperationBehavior
{
private Type _resolverType = null;
public DataContractResolverAttribute (Type resolver)
{
_resolverType = resolver;
}
public void AddBindingParameters (OperationDescription description, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior (OperationDescription description, ClientOperation proxy)
{
AddResolverToOperation(description);
}
public void ApplyDispatchBehavior (OperationDescription description, DispatchOperation dispatch)
{
AddResolverToOperation(description);
}
public void Validate (OperationDescription description)
{
}
private void AddResolverToOperation (OperationDescription description)
{
DataContractSerializerOperationBehavior dcs = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcs != null)
{
dcs.DataContractResolver = Activator.CreateInstance(_resolverType) as DataContractResolver;
}
}
}
另外,我已将此属性分配给操作:
[OperationContract]
[FaultContract(typeof(string))]
[DataContractResolver(typeof(CustomResolver))]
RuleResultData ExecuteRuleObj (object context, int ruleId);
CustomResolver是DataContractResolver的后代:
class CustomResolver: DataContractResolver
{
public override Type ResolveName (string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
{
// ... not significant here ...
}
public override bool TryResolveType (Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
{
// ... not significant here ...
}
}
在调试时我看到Resolver被成功替换(在AddResolverToOperation中设置一个断点),但是在调用时我没有看到任何效果(ResolveName和TryResolveType中的断点都没有被触发)。
请提供关于这种令人讨厌的解析器行为的线索。
提前致谢。 Alexey Vishnyakov,俄罗斯。