2013-11-27 64 views
8

我正在尝试使用DataContractSerializer将类加载到包含泛型类型的xml文件中。我有保存工作,但已经意识到我无法加载它,因为我没有反序列化器knownTypes的列表。我可以在不参考类型的情况下反序列化泛型吗?

有没有一种序列化/反序列化这个类,这将允许我反序列化它,而无需直接引用任何存储的类型?

这里是我SessionVariables类,我想保存/加载:

[DataContract] 
public class SessionVariables 
{ 
    [DataMember] 
    private Dictionary<Type, ISessionVariables> _sessionVariables = new Dictionary<Type, ISessionVariables>(); 
    private object _syncLock = new object(); 

    public T Get<T>() 
     where T : ISessionVariables, new() 
    { 
     lock (_syncLock) 
     { 
      ISessionVariables vars = null; 

      if (_sessionVariables.TryGetValue(typeof(T), out vars)) 
       return (T)vars; 

      vars = new T(); 
      _sessionVariables.Add(typeof(T), vars); 

      return (T)vars; 
     } 
    } 

    public IList<Type> GetKnownTypes() 
    { 
     IList<Type> knownTypes = new List<Type>(); 

     knownTypes.Add(this.GetType().GetType()); // adds System.RuntimeType 

     foreach (Type t in _sessionVariables.Keys) 
     { 
      if (!knownTypes.Contains(t)) 
       knownTypes.Add(t); 
     } 

     return knownTypes; 
    } 
} 

应用程序的不同模块扩展ISessionVariables接口来创建自己的一套会话变量,像这样:

[DataContract] 
public class ModuleASessionVariables : ISessionVariables 
{ 
    [DataMember] 
    public string ModuleA_Property1{ get; set; } 
    [DataMember] 
    public string ModuleA_Property2 { get; set; } 
} 


[DataContract] 
public class ModuleBSessionVariables : ISessionVariables 
{ 
    [DataMember] 
    public string ModuleB_Property1{ get; set; } 
    [DataMember] 
    public string ModuleB_Property2 { get; set; } 
} 

而且SessionVariables类的单一实例用于访问会话变量,像这样:

singletonSessionVariables.Get<ModuleASessionVariables>().ModuleA_Property1 
singletonSessionVariables.Get<ModuleBSessionVariables>().ModuleB_Property2 

我得到了保存这样的工作:

using (FileStream writer = new FileStream(@"C:\test.txt", FileMode.Create)) 
{ 
    DataContractSerializer dcs = new DataContractSerializer(typeof(SessionVariables), singletonSessionVariables.GetKnownTypes()); 
    dcs.WriteObject(writer, singletonSessionVariables); 
    writer.Close(); 
} 

但是这种方法不起作用反序列化类,因为我不知道它是已知类型。

当我没有直接引用任何类型的类型时,是否可以序列化和反序列化泛型类型?如果是这样,怎么样?

+1

:/我会使用NetDataContractSerializer,它包含结果中的类型信息。 – Will

+0

不要认为这是可能的:如果类型本身是未知的,我们将如何创建一个类型的实例? – Tigran

+0

@意愿谢谢,我不知道之前存在!你应该写一个答案:) – Rachel

回答

3

这里的问题是,你不只是想序列化的数据,但你也想序列数据有关数据,即(CUE戏剧性的花栗鼠)

在这种情况下,元数据是最初保存数据的模型的类型。通常情况下,这不是问题,但正如你发现如果你在设计中利用多态性,你的单一集合可能包含两个或更多的不同类型,每个类型需要被反序列化为它们的原始类型。

这通常通过将此类型元数据保存到序列化结果来完成。不同的序列化方法以不同的方式做到这一点。 Xaml序列化使用与.net命名空间关联的xml命名空间,然后将原始类型名称后的元素命名。 Json.net通过保存到json对象的特定命名值完成此操作。

默认的DataContractSerializer不能识别类型。因此,您需要将其替换为能够理解.NET类型系统的版本,并且可以将类型元数据序列化/反序列化到生成的xml。幸运的是,框架中已经存在一个NetDataContractSerializer

这就是你如何填补仅链接的答案。贵族。

+0

这很好,没有参考所需的外部模块库。我必须做的唯一改变是用'[DataMember]'属性标记'_syncLock'对象,或者将其反序列化为'null'。我正在寻找一种解决方法。谢谢:) – Rachel

0

您可以使用自定义DataContractResolver完成此操作。这允许您插入反序列化管道,并根据序列化图中找到的类型/名称空间提供要反序列化的类型。

这里有一个关于它的好文章: http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/21/wcf-extensibility-data-contract-resolver.aspx

■设计有一个解析器的实现,可用于在其网站类型的动态发现:http://idesign.net/Downloads/GetDownload/1848(你可能会作出一些修改,以支持泛型)

+1

给你的提示:这个解决方案需要.net 4--我只是注意到你的问题中的.net3-5标签。 – JMarsch

相关问题