使用DataContractSurrogate進行反序列化,您可以使用DataContractSurrogate解決這個,它用List替換IList。
public class CustomDataContractSurrogate : IDataContractSurrogate
{
// The only function you should care about here. The rest don't do anything, just default behavior.
public Type GetDataContractType(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(ICollection<>)))
{
return (typeof(List<>).MakeGenericType(type.GetGenericArguments().Single()));
}
return type;
}
public object GetObjectToSerialize(object obj, Type targetType)
{
return obj;
}
public object GetDeserializedObject(object obj, Type targetType)
{
return obj;
}
public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
{
return null;
}
public object GetCustomDataToExport(Type clrType, Type dataContractType)
{
return null;
}
public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
{
}
public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
{
return null;
}
public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
{
return typeDeclaration;
}
}
基本上就是這樣,你只需要與代理創建DataContractSerializer的實例,並用它來反序列化(系列化都不會有問題),例如:
var serializer = new DataContractSerializer(type, new Type[]{}, Int32.MaxValue, false, true, new CustomDataContractSurrogate());
或其任何其他構造函數採用代理。
或者,(作爲獎金答案)如果你使用的應用程序/ web.config中定義的服務工作,你可以定義創建與上述代理數據合同串行定製行爲:
public class CustomDataContractSerializerBehavior : DataContractSerializerOperationBehavior
{
public CustomDataContractSerializerBehavior(OperationDescription operation)
: base(operation)
{
}
public CustomDataContractSerializerBehavior(OperationDescription operation, DataContractFormatAttribute dataContractFormatAttribute)
: base(operation, dataContractFormatAttribute)
{
}
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns,
IList<Type> knownTypes)
{
return new DataContractSerializer(type, knownTypes, Int32.MaxValue, false, true, new CustomDataContractSurrogate());
}
public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name,
XmlDictionaryString ns, IList<Type> knownTypes)
{
return new DataContractSerializer(type, knownTypes, Int32.MaxValue, false, true, new CustomDataContractSurrogate());
}
}
最後您可以使用此行爲:
public static IMyDataServiceContract CreateService()
{
var factory = new ChannelFactory<IMyDataServiceContract>("MyServiceName");
SetDataContractSerializerBehavior(factory.Endpoint.Contract);
return factory.CreateChannel();
}
private static void SetDataContractSerializerBehavior(ContractDescription contractDescription)
{
foreach (OperationDescription operation in contractDescription.Operations)
{
ReplaceDataContractSerializerOperationBehavior(operation);
}
}
private static void ReplaceDataContractSerializerOperationBehavior(OperationDescription description)
{
DataContractSerializerOperationBehavior dcsOperationBehavior =
description.Behaviors.Find<DataContractSerializerOperationBehavior>();
if (dcsOperationBehavior != null)
{
description.Behaviors.Remove(dcsOperationBehavior);
description.Behaviors.Add(new CustomDataContractSerializerBehavior(description));
}
}
來完成這項工作,調用上面CreateSe在某處創建頻道。
其實我不想在我的xml文件中存儲類型信息。但似乎MS已經實現了一些機制來採取特定類型,如果沒有給出(像只有一個接口)。問題是他們如何解決它,你能以某種方式配置這種機制(可能通過我的接口/類上的Attribute或通過配置DataContractSerializer實例) – Oliver 2010-05-17 11:47:33
集合類型的Data Contract序列化行爲的完整文檔在這裏在MSDN上:http://msdn.microsoft.com/en-us/library/aa347850.aspx 讀取,恐怕你無法控制爲集合接口實例化的類型。 – Lucero 2010-05-17 15:43:53
我對你提到的頁面做了一個粗略的閱讀,發現你的意思是:「類型的選擇是內置於WCF」。所以這感覺非常不舒服。我讓這個問題開放一段時間,也許有人有另一個想法。但我認爲不會有更好的答案。 *嘆息* – Oliver 2010-05-18 06:28:30