Определить тип DataContract из XElement - PullRequest
3 голосов
/ 09 июля 2011

Я использую пространство имен System.Runtime.Serialization за пределами WCF и хотел бы выяснить, что представляет собой тип элемента - существует ли преобразователь имен?Мне бы очень хотелось что-то вроде:

Type ResolveName(XmlQualifiedName typeName);

Я вижу, что во внутренней работе WCF есть что-то похожее, но я не могу найти публичную.

Спасибо!

Ответы [ 2 ]

1 голос
/ 09 июля 2011

Поскольку я все еще думал, что мне нужна эта функциональность, я пошел и написал класс, чтобы получить информацию. Я использовал 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(...);
0 голосов
/ 09 июля 2011

Суть сериализации на основе контракта, в частности DataContractSerialization, заключается в том, что она не привязана к определенным типам (примечание: NetDataContractSerializer не разделяет это). Таким образом, может быть ноль, один или много типов кандидатов. Какой бы он выбрал?

Так нет; AFAIK, что в принципе не возможно. Вы могли бы возможно использовать рефлексию для всех типов во всех загруженных сборках, ища [DataContract] и, конечно, применять тесты вручную.

Обычно у вас есть существующая информация о типе (либо корневой тип, либо текущий тип), поэтому у вас есть только небольшой набор типов-кандидатов (KnownType и т. Д.) Для рассмотрения.

...