我可以在不参考类型的情况下反序列化泛型吗?

时间:2013-11-27 14:34:24

标签: c# .net-3.5 datacontractserializer

我正在尝试使用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();
}

但是这个方法不能反序列化类,因为我不知道它的已知类型。

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

2 个答案:

答案 0 :(得分:4)

这里的问题是你不仅想要序列化数据,而且还想序列化关于数据的数据,即(提示戏剧性的花栗鼠)元数据

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

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

默认的DataContractSerializer不支持Type。因此,您需要将其替换为了解.NET Type系统的版本,并且可以将Type元数据序列化/反序列化为生成的xml。幸运的是,框架中已存在一个NetDataContractSerializer

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

答案 1 :(得分:0)

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

这是一篇很好的文章: http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/21/wcf-extensibility-data-contract-resolver.aspx

IDesign有一个解析器的实现,可用于动态发现其网站上的类型:http://idesign.net/Downloads/GetDownload/1848(您可能需要进行一些修改才能处理泛型)