【问题标题】:How do I find all the types used by an object and it's members recursively?如何递归查找对象使用的所有类型及其成员?
【发布时间】:2011-09-10 02:24:12
【问题描述】:

我正在尝试使用 DataContractJsonSerializer 序列化和反序列化包含不同类型 object[] 的 c# 对象。

我需要找到 XmlRequest 使用的所有类型以及它的 object[] 中的对象,因此我将类型列表传递给 DataContractJsonSerializer。

XmlRequest 中的 object[] 将包含不同的类型。 TypeX、TypeY、字符串、int、TypeZ

var sr = new DataContractJsonSerializer(typeof(XmlRequest), knownTypes);

Xml 请求类:

[DataContract]
    public class XmlRequest
    {
        [DataMember]
        public object[] Parameters { get; set; }

        [DataMember]
        public string Name { get; set; }

    }

【问题讨论】:

  • 此时我不知道如果没有已填充其他对象的对象实例是可能的。 “类型”是 object[],因此无法仅使用类型在对象数组中找到对象的类型。

标签: c# .net


【解决方案1】:
public void CollectTypes(Type type, HashSet<Type> types)
{
    if (types.Contains(type)) return;
    types.Add(type);

    foreach (FieldInfo fi in type.GetFields(BindingFlags.Instance | BindingFlags.Public))
    {
        if (!fi.IsInitOnly)
        {
            CollectTypes(fi.FieldType, types);
        }
    }

    foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Instance | BindingFlags.Public))
    {
        if (pi.CanWrite && pi.CanRead)
        {
            CollectTypes(pi.PropertyType, types);
        }
    }
}

用法:

object[] parameters = ....;
HashSet<Type> types = new HashSet<Type>();
foreach(object p in parameters)
{
    if (p != null)
    {
      CollectTypes(p.GetType(), types)
    }
}

var sr = new DataContractJsonSerializer(typeof(XmlRequest), types.ToArray());

如果反序列化程序能够写入只读成员,则不需要检查给定成员是否为只读。

【讨论】:

  • 我试过这个并意识到为什么这是不可能的。类型是对象[]。我们无法仅从类型声明中获取 object[] 中对象的类型信息。
【解决方案2】:

我看到了问题的答案,如所写,但想进一步探索。

您是否尝试对 XmlRequest 进行泛化,以便它可以接受一个或多个单一类型的对象,如:

Object[] ary = new Object[] { new MyObject(), new MyObject() };

或者您实际上是在将多种类型放入数组中,如:

Object[] ary = new Object[] { new MyObject(), new MyOtherObject() };

如果您使用的是前者,请考虑使用泛型。对于 Request,不是最异构的解决方案,但 XmlRequest 是加载对象、单一类型数组等的绝妙方式。

如果您执行前者并使用泛型并且不需要较重的“检查每种类型”方法,则序列化更容易,因为参数数组是强类型的。

【讨论】:

  • 不幸的是 object[] 中的对象与您的第二个示例不同。
  • 那么杰森的回答可能是一个更好的起点。 :-( 我目前对服务使用泛型,它允许 WCF 4 中的默认 JSON 序列化,所以我想建议这条路线,如果可能的话,因为它更容易“锄头”。
【解决方案3】:

我想出了如何通过配置来做到这一点,而不是试图在运行时发现这些项目。

<system.runtime.serialization>
        <dataContractSerializer>
            <declaredTypes>
                <add type="Whatever.XmlRequest, Whatever, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
                    <knownType type="WhateverLibary.Parameter, WhateverLibary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
                </add>
            </declaredTypes>
        </dataContractSerializer>
    </system.runtime.serialization>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-13
    • 2019-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    相关资源
    最近更新 更多