从XElement确定数据契约类型

本文关键字:契约 类型 数据 XElement | 更新日期: 2023-09-27 18:01:33

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

Type ResolveName(XmlQualifiedName typeName);

我看到在WCF的内部工作中有类似的东西,但我似乎找不到一个公开的

谢谢!

从XElement确定数据契约类型

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

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(...);

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

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

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