我想制定一个人为的设想,但它具有坚实的实际基础.想象一个集合类型COuter,它是另一个集合类型CInner的实例的包装器.两者都实现了IList(更别提了T).
此外,COuter实例被隐藏在一些对象图中,其根(我们将其称为R)从WCF服务方法返回.
我的问题是如何自定义WCF序列化过程,以便在返回R时,序列化COuter实例的请求将通过我的代码进行路由,这将提取CInner并将其传递给序列化器.因此,接收端仍然获得R,在对象图中只找不到COuter实例.
我希望WCF如何序列化方法调用?将包含答案,遗憾的是,那里提到的文章(http://msdn.microsoft.com/en-us/magazine/cc163569.aspx)几乎没有提到使用IDataContractSurrogate接口可以实现高级序列化方案,但没有给出详细信息.另一方面,我真的很想看到一个有效的例子.
非常感谢你提前.
编辑
我创建了一个简单的WCF示例,它演示了这个问题.该档案位于此处 - https://docs.google.com/leaf?id=0B2pbsdBJxJI3NzFiNjcxMmEtMTM5Yy00MWY2LWFiMTUtNjJiNjdkYTU1ZTk4&sort=name&layout=list&num=50
它包含三个小项目:
该服务定义了一个方法,该方法返回一个HelloServiceResult类型的实例,该实例包含对COuterList包装CInnerList类型的类型的引用.参考被指定为IMyListInterface,其中两个COuterList和CInnerList实现该接口.我需要的是,当结果在传输到客户端之前被序列化时,COuterList引用将被包装CInnerList引用替换.我知道这可以通过利用WCF的现有功能来完成,我只是不知道如何.
以下是如何实现自己的代理:
class YourCustomTypeSurrogate : IDataContractSurrogate
{
public Type GetDataContractType(Type type)
{
// Just for reference
//if (typeof(OldType).IsAssignableFrom(type))
//{
// return typeof(NewType);
//}
return type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
// This method is called on serialization.
//if (obj is OldType)
//{
// // ... use the XmlSerializer to perform the actual serialization.
// NewType newObj = new NewType();
// return newObj;
//}
return obj;
}
public object GetDeserializedObject(object obj, Type targetType)
{
// This method is called on deserialization.
// If PersonSurrogated is being deserialized...
//if (obj is NewType)
//{
// OldType newObj = new OldType();
// return newObj;
//}
return obj;
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
// This method is called on schema import.
//if (typeNamespace.Equals("Your Type Namespace"))
//{
// if (typeName.Equals("NewType"))
// {
// return typeof(OldType);
// }
//}
return null;
}
public System.CodeDom.CodeTypeDeclaration ProcessImportedType(System.CodeDom.CodeTypeDeclaration typeDeclaration, System.CodeDom.CodeCompileUnit compileUnit)
{
// Not used in this sample.
// You could use this method to construct an entirely
// new CLR type when a certain type is imported, or modify a generated
// type in some way.
return typeDeclaration;
}
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
// Not used in this sample
return null;
}
public object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, Type dataContractType)
{
// Not used in this sample
return null;
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
// Not used in this sample
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您创建自定义序列化程序操作行为:
public class CustomDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
public CustomDataContractSerializerOperationBehavior(OperationDescription operationDescription) : base(operationDescription) { }
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
return new DataContractSerializer(
type /*typeof OldType*/,
knownTypes,
int.MaxValue /*maxItemsInObjectGraph */,
false /*ignoreExtensionDataObject*/,
true /*preserveObjectReferences*/,
new YourCustomTypeSurrogate());
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(
type /*typeof OldType*/,
knownTypes,
int.MaxValue /*maxItemsInObjectGraph */,
false /*ignoreExtensionDataObject*/,
true /*preserveObjectReferences*/,
new YourCustomTypeSurrogate());
}
}
Run Code Online (Sandbox Code Playgroud)
之后,创建一个属性以将上述操作行为应用于操作合同:
public class CustomDataContractFormatAttribute : Attribute, IOperationBehavior
{
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
{
}
public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
{
ReplaceDataContractSerializerOperationBehavior(description);
}
public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
{
ReplaceDataContractSerializerOperationBehavior(description);
}
public void Validate(OperationDescription description)
{
}
private static void ReplaceDataContractSerializerOperationBehavior(OperationDescription description)
{
DataContractSerializerOperationBehavior dcs = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcs != null)
description.Behaviors.Remove(dcs);
description.Behaviors.Add(new CustomDataContractSerializerOperationBehavior(description));
}
}
Run Code Online (Sandbox Code Playgroud)
最后,将此属性应用于操作:
[OperationContract]
[CustomDataContractFormat]
void DoWork();
Run Code Online (Sandbox Code Playgroud)
如果要将此应用于整个服务,则可以自定义"服务行为"而不是"操作行为".
以下是用于创建此示例的引用:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.idatacontractsurrogate.aspx
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/e4d55f3f-86d1-441d-9187-64fbd8ab2b3d/