从对象中删除null属性

本文关键字:null 属性 删除 对象 | 更新日期: 2023-09-27 18:25:42

,我有一个类,其中我有三个属性,现在我想做什么,如果在对象中,如果有null或empty中的任何一个,那么我想从对象中删除它。下面是我的代码。

public class TestClass
{
    public string Name { get; set; }
    public int ID { get; set; }
    public DateTime? DateTime { get; set; }
    public string Address { get; set; }
}
       TestClass t=new TestClass();
        t.Address="address";
        t.ID=132;
        t.Name=string.Empty;
        t.DateTime=null;

现在我想要TestClass的对象,但在Name和DateTime属性中不应该是它们在对象中的,有可能吗?请帮助我

从对象中删除null属性

我很无聊,在LINQPad 中得到了这个

void Main()
{
    TestClass t=new TestClass();
    t.Address="address";
    t.ID=132;
    t.Name=string.Empty;
    t.DateTime=null;
    t.Dump();
    var ret = t.FixMeUp();
    ((object)ret).Dump();
}
public static class ReClasser
{
    public static dynamic FixMeUp<T>(this T fixMe)
    {
        var t = fixMe.GetType();
        var returnClass = new ExpandoObject() as IDictionary<string, object>;
        foreach(var pr in t.GetProperties())
        {
            var val = pr.GetValue(fixMe);
            if(val is string && string.IsNullOrWhiteSpace(val.ToString()))
            {
            }
            else if(val == null)
            {
            }
            else
            {
                returnClass.Add(pr.Name, val);
            }
        }
        return returnClass;
    }
}
public class TestClass
{
    public string Name { get; set; }
    public int ID { get; set; }
    public DateTime? DateTime { get; set; }
    public string Address { get; set; }
}

没有从单个对象中删除属性这样的概念。类型决定了存在哪些属性,而不是单个对象。

特别是,总是有这样的方法是有效的:

public void ShowDateTime(TestClass t)
{
    Console.WriteLine(t.DateTme);
}

该代码无法知道您是否想从t引用的对象中"删除"DateTime属性。如果该值为null,它只会得到该值-这很好。但您不能删除属性本身。

如果在某个地方列出对象的属性,则应该在那里进行过滤。

编辑:好的,不,你给了我们一些背景:

好的,我使用的是Schemaless数据库,所以null和空值也在数据库中存储空间,这就是的原因

因此,在您正在使用的填充数据库的代码中,不要设置任何与具有null值的属性相对应的字段。这纯粹是数据库总体问题,而不是对象本身的问题。

(我还认为,你应该考虑这样做能真正节省多少空间。你真的这么在乎吗?)

下面是接受答案的"稍微"更清晰、更短的版本。

        /// <returns>A dynamic object with only the filled properties of an object</returns>
        public static object ConvertToObjectWithoutPropertiesWithNullValues<T>(this T objectToTransform)
        {
            var type = objectToTransform.GetType();
            var returnClass = new ExpandoObject() as IDictionary<string, object>;
            foreach (var propertyInfo in type.GetProperties())
            {
                var value = propertyInfo.GetValue(objectToTransform);
                var valueIsNotAString = !(value is string && !string.IsNullOrWhiteSpace(value.ToString()));
                if (valueIsNotAString && value != null)
                {
                    returnClass.Add(propertyInfo.Name, value);
                }
            }
            return returnClass;
        }

您可以利用动态类型:

class Program
{
    static void Main(string[] args)
    {
        List<dynamic> list = new List<dynamic>();
        dynamic
            t1 = new ExpandoObject(),
            t2 = new ExpandoObject();
        t1.Address = "address1";
        t1.ID = 132;
        t2.Address = "address2";
        t2.ID = 133;
        t2.Name = "someName";
        t2.DateTime = DateTime.Now;
        list.AddRange(new[] { t1, t2 });
        // later in your code
        list.Select((obj, index) =>
            new { index, obj }).ToList().ForEach(item =>
        {
            Console.WriteLine("Object #{0}", item.index);
            ((IDictionary<string, object>)item.obj).ToList()
                .ForEach(i =>
                {
                    Console.WriteLine("Property: {0} Value: {1}",
                        i.Key, i.Value);
                });
            Console.WriteLine();
        });
        // or maybe generate JSON
        var s = JsonSerializer.Create();
        var sb=new StringBuilder();
        var w=new StringWriter(sb);
        var items = list.Select(item =>
        {
            sb.Clear();
            s.Serialize(w, item);
            return sb.ToString();
        });
        items.ToList().ForEach(json =>
        {
            Console.WriteLine(json);
        });
    }
}

可能是接口会很方便:

public interface IAdressAndId
    {
        int ID { get; set; }
        string Address { get; set; }
    }
    public interface INameAndDate
    {
        string Name { get; set; }
        DateTime? DateTime { get; set; }
    }
    public class TestClass : IAdressAndId, INameAndDate
{
    public string Name { get; set; }
    public int ID { get; set; }
    public DateTime? DateTime { get; set; }
    public string Address { get; set; }
}

创建对象:

IAdressAndId t = new TestClass()
            {
                Address = "address",
                ID = 132,
                Name = string.Empty,
                DateTime = null
            };

此外,您可以将接口放在单独的命名空间中,并将类声明为内部。之后创建一些公共工厂,这些工厂将创建类的实例。