【问题标题】:Determine DataContract type from XElement从 XElement 确定 DataContract 类型
【发布时间】:2011-07-09 17:26:15
【问题描述】:

我在 WCF 之外使用 System.Runtime.Serialization 命名空间,并且想了解元素代表的类型 - 是否有名称解析器?我真的很喜欢这样的东西:

Type ResolveName(XmlQualifiedName typeName);

我看到 WCF 的内部工作方式有类似的东西,但我似乎找不到公开的。

谢谢!

【问题讨论】:

    标签: c# xml-serialization datacontract


    【解决方案1】:

    因为我仍然认为我需要这个功能,所以我已经编写了一个类来获取信息。我使用 Impromptu-Interface 来加速反射位,但这整个过程让我很恼火。

    public class DataContractNameResolver
    {
        private Type TypeOfDataContract = null;
        private Dictionary<System.Xml.XmlQualifiedName, Type> xmlNames = new Dictionary<System.Xml.XmlQualifiedName, Type>();
    
        internal void PrecacheBaseTypes(IEnumberable<Type> types)
        {
            if (TypeOfDataContract == null)
            {
                TypeOfDataContract = Type.GetType("System.Runtime.Serialization.DataContract, System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
            }
    
            lock (xmlNames)
            {
                var remaining = new Queue<Type>(types.Except(xmlNames.Values));
    
                while (remaining.Count > 0)
                {
                    Type next = remaining.Dequeue();
    
                    var dc = Impromptu.InvokeMember(TypeOfDataContract.WithStaticContext(), "GetDataContract", next);
                    IDataContract result = Impromptu.ActLike<IDataContract>(dc);
    
                    xmlNames.Add(new System.Xml.XmlQualifiedName(result.Name.Value, result.Namespace.Value), next);
                }
            }
        }
    
        public Type ResolveName(System.Xml.XmlQualifiedName typeName)
        {
            if (xmlNames.ContainsKey(typeName))
            {
                return xmlNames[typeName];
            }
            return null;
        }
    }
    

    这个类的使用类似于:

    var nameResolver = new DataContractNameResolver();
    nameResolver.PrecacheBaseTypes(new[] { typeof(SampleOne), typeof(SampleTwo) });
    var resultType = nameResolver.ResolveName(...);
    

    【讨论】:

      【解决方案2】:

      基于契约的序列化 ala DataContractSerialization 的部分要点在于它不依赖于特定类型(注意:NetDataContractSerializer 不共享这一点)。因此,可能有零个、一个或多个候选类型。它会选择哪个?

      所以不; AFAIK 这基本上是不可能的。您可以也许对所有加载的程序集中的所有类型使用反射,当然,寻找 [DataContract] 并手动应用他的测试。

      通常您有现有的类型信息(根类型或当前类型),因此您只需考虑一小组候选类型(KnownType 等)。

      【讨论】:

      • 嗯,这很公平 - 我不介意它给我一个候选类型列表,甚至,或者接受一个“已知类型”列表,就像 DataContractSerializer 一样。要点是我现在不想反序列化它,但我想知道如果我这样做会加载什么。 (延迟加载的东西。)我正在研究一个使用反射(ugh)和内部DataContract 类的解决方案。感谢您的观看!
      • 好吧,我希望在我正在处理的应用程序中有大量(可能数十万)这些对象,我将简单地存储对象的路径(序列化到硬盘驱动器,而不是作为 WCF 合同),因为我希望应用程序一次只能使用较小的(例如,数百个)子集。我们正在使用 DataContract 序列化,以便 XPath 可用于通过外部工具分析文件,它可以节省学习/编写新的序列化程序。
      • @Matt 所以我不能让你对不同的序列化程序感兴趣,然后:) 但是我怀疑你的场景在技术上比看起来更困难。在 XML 中,相同的 元素 名称可以在不同的上下文中引用不同的类型。
      • 谢谢,Marc - 是的,我知道它可以引用不同的类型(这是我使用命名空间+名称而不是显式放入程序集限定类型名称的部分原因) - 完成后,我将发布基于反射的示例。感谢您听到我的声音!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 2014-03-14
      • 1970-01-01
      • 2011-12-25
      相关资源
      最近更新 更多