C#:如何使用反射从通用对象中删除所有null属性?

时间:2009-05-03 19:35:31

标签: c# reflection

我想删除通用对象中的所有null属性。它不一定是递归的,一层深也没关系。

我需要的原因是JSON序列化的自定义JavascriptConvertor实现,它给了我:{“Name”:“Aleem”,“Age”:null,“Type”:“Employee”}

我想跳过null对象。

此任务的函数接受objct并返回一个Dictionary:

IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)

所以我想从obj中删除所有null属性。所有属性都有getter,但如果未设置该属性,则getter返回null

4 个答案:

答案 0 :(得分:4)

您可以实现自己的JavaScriptConverter来处理类型的序列化。然后,您可以完全控制属性的序列化方式。

@Richards回答提供了一个很好的Serialize方法实现。

反序列化方法非常相似,但我会将实现留给您。现在JavaScriptConverter的唯一缺点是它必须从某个地方获取支持的类型。要么像这样硬编码:

public override IEnumerable<Type> SupportedTypes
{ 
    get
    {
        var list = new List<Type>{ typeof(Foo), typeof(Bar)...};
        return list.AsReadOnly();
    }
}

...或使其可配置,例如通过类构造函数。

答案 1 :(得分:4)

以下内容可能会解决问题:

public IDictionary<string, object> GetNonNullProertyValues(object obj)
{
    var dictionary = new Dictionary<string, object>();

    foreach (var property in obj.GetType().GetProperties())
    {
        var propertyValue = property.GetValue(obj, null);
        if (propertyValue != null)
        {
            dictionary.Add(property.Name, propertyValue);
        }
    }

    return dictionary;
}

注意:此方法不处理索引属性。

答案 2 :(得分:1)

 using System.IO;
 using System.Runtime.Serialization.Json;

    public static class JsonExtensions
    {
        public static string ToJson<T>(this T instance) 
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream memoryStream = new MemoryStream())
            {
                serializer.WriteObject(memoryStream, instance);

                memoryStream.Flush();
                memoryStream.Position = 0;

                using (var reader = new StreamReader(memoryStream))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        public static T FromJson<T>(this string serialized) 
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (StreamWriter writer = new StreamWriter(memoryStream))
                {
                    writer.Write(serialized);
                    writer.Flush();

                    memoryStream.Position = 0;

                    return (T)serializer.ReadObject(memoryStream);
                }
            }
        }
    }

答案 3 :(得分:0)

您可能想要创建某种包装对象,只有在它们不为空时才会公开它所包装的成员。

您可能还想查看C#的第4版。来自the wikipedia entry for duck typing

  

C#的第4版发布有额外的   类型注释指示   编译器安排类型检查   在运行时发生的类而不是   比编译时间,包括   运行时类型检查代码   编译输出。这样的添加允许   享受大部分的语言   只有鸭子打字的好处   缺点是需要识别   并指定这样的动态类   编译时间。