如何以递归方式找到对象及其成员使用的所有类型?

时间:2011-06-07 13:40:21

标签: c# .net

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

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

XmlRequest中的object []将包含不同的类型。 TypeX,TypeY,string,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; }

    }

3 个答案:

答案 0 :(得分:2)

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

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

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

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

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

如果您正在使用前者,请考虑使用泛型。对于请求,不是最异构的解决方案,但XmlRequest是加载对象,单个类型的数组等的好方法。

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

<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>