开发者

How do I find all the types used by an object and it's members recursively?

I'm trying to use the DataContractJsonSerializer to serialize 开发者_开发知识库and deserialize a c# object that contains an object[] of differing types.

I need to find all the types used by the XmlRequest and the objects in it's object[] so I an pass the list of Types to the DataContractJsonSerializer.

The object[] in XmlRequest will contain different types. TypeX, TypeY, string, int, TypeZ

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

Xml Request Class:

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

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

    }


I see the answer to the question, as written, but want to explore further.

Are you trying to genericize the XmlRequest so it can take one or more objects of a single type, as in:

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

Or are you actually throwing multiple types into an array, as in:

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

If you are doing the former, consider using Generics. For a Request, not the most heterogenous solution, but XmlRequest is a wonderful way to load an object, an array of a single type, etc.

Serialization is easier if you are doing the former and use generics and does not require the heavier "check each type" approach, as the Parameters array is strongly typed.


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

Usage:

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

The check if a given member is read-only is not required if the deserializer is able to write read-only members.


I figured out how to do this through configuration instead of trying to discover these items at runtime.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜