C# 如果对象的所有属性在C中都为null,则将对象设置为null#

C# 如果对象的所有属性在C中都为null,则将对象设置为null#,c#,asp.net,asp.net-mvc,C#,Asp.net,Asp.net Mvc,我想写一个函数,它可以转换对象的每个属性和子属性。如果一个属性的所有属性都为null,那么我会将该属性设置为null。我将用一个例子来解释 例如,如果TeacherName和TeacherName都为null,那么我想将Teacher设置为null。然后,如果ExamMark和ExamName和Teacher为空,则Exam将为空 您可以从这个链接中看到类似我的问题的json版本 我写了这个方法。但这只是第一步。但我需要递归的子类。如何将此方法转换为递归? public static objec

我想写一个函数,它可以转换对象的每个属性和子属性。如果一个属性的所有属性都为null,那么我会将该属性设置为null。我将用一个例子来解释

例如,如果
TeacherName
TeacherName
都为null,那么我想将
Teacher
设置为null。然后,如果
ExamMark
ExamName
Teacher
为空,则
Exam
将为空

您可以从这个链接中看到类似我的问题的json版本

我写了这个方法。但这只是第一步。但我需要递归的子类。如何将此方法转换为递归?

public static object ConvertToNull(object obj)
{
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();

    var mainClassProperties = properties.Where(p => p.PropertyType.Assembly == objType.Assembly);

    foreach (var mainClassProperty in mainClassProperties)
    {
       object propValue = mainClassProperty.GetValue(obj, null);
       var classAllProperties = propValue.GetType().GetProperties();

       if (propValue.GetType().GetProperties().All(propertyInfo => propertyInfo.GetValue(propValue) == null))
       {
           mainClassProperty.SetValue(obj, null);
       }
   }
    return obj;
}
你所要求的实际上是一种反模式。它的作用是在代码中传播大量空检查的需求。您不仅需要检查所有属性是否为null,还需要检查对象在使用时是否为null。此外,反射非常慢,如果您经常这样做,您的应用程序将陷入困境

你应该调查这件事。它基本上做了您希望它做的事情,并且您删除了所有讨厌的空检查:

公共班级学生
{
公共字符串名称{get;set;}
公共字符串姓氏{get;set;}
公共广播地址{get;set;}
公开考试{get;set;}
公共静态学生NullStudent{get;}=新学生
{
Name=null,
姓氏=空,
地址=地址。空地址,
考试,
}
}
您可以对代码中以这种方式运行的每个对象执行此操作(您可以看到我也对嵌套地址和检查类型执行了此操作),然后不再执行此操作:

if(Student.EverythingIsNull){Student=null}
如果(学生为空){//do null stuff}
您可以这样做:

if(item==Student.NullStudent){//do null stuff}
这将导致代码更加清晰,您的意图更加突出,并且您可以在每个对象中明确定义构成null的内容。

你所要求的实际上是一种反模式。它的作用是在代码中传播大量空检查的需求。您不仅需要检查所有属性是否为null,还需要检查对象在使用时是否为null。此外,反射非常慢,如果您经常这样做,您的应用程序将陷入困境

你应该调查这件事。它基本上做了您希望它做的事情,并且您删除了所有讨厌的空检查:

公共班级学生
{
公共字符串名称{get;set;}
公共字符串姓氏{get;set;}
公共广播地址{get;set;}
公开考试{get;set;}
公共静态学生NullStudent{get;}=新学生
{
Name=null,
姓氏=空,
地址=地址。空地址,
考试,
}
}
您可以对代码中以这种方式运行的每个对象执行此操作(您可以看到我也对嵌套地址和检查类型执行了此操作),然后不再执行此操作:

if(Student.EverythingIsNull){Student=null}
如果(学生为空){//do null stuff}
您可以这样做:

if(item==Student.NullStudent){//do null stuff}

这将导致更清晰的代码,您的意图更加突出,并且您可以在每个对象中明确定义什么构成空值。

看看这一点,GetValueOrFull应该可以工作并完成您需要的工作,没有在所有可能的用例中进行测试,但如果不能在所有情况下都工作,则可以对其进行一些调整

public static bool IsSimpleType(Type type)
{
    return
        type.IsPrimitive ||
        new Type[] {
    typeof(Enum),
    typeof(String),
    typeof(Decimal),
    typeof(DateTime),
    typeof(DateTimeOffset),
    typeof(TimeSpan),
    typeof(Guid)
        }.Contains(type) ||
        Convert.GetTypeCode(type) != TypeCode.Object ||
        (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) && IsSimpleType(type.GetGenericArguments()[0]))
        ;
}
public object GetValueOrNull(object obj)
{
    if (obj == null) return null;
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    var simpleTypes = properties.Where(t => IsSimpleType(t.PropertyType));

    var nonValueTypes = properties.Where(p => !simpleTypes.Contains(p));
    foreach (var child in nonValueTypes)
    {
        child.SetValue(obj, GetValueOrNull(child.GetValue(obj)));
    }
    return simpleTypes.All(z => z.GetValue(obj) == null) && nonValueTypes.All(z => z.GetValue(obj) == null) ? null : obj;
}

希望它能有所帮助:)

看看这个,GetValueOrFull应该可以工作并完成您需要的工作,没有在所有可能的用例中进行测试,但是如果不能在所有情况下都工作,可以对它进行一些调整

public static bool IsSimpleType(Type type)
{
    return
        type.IsPrimitive ||
        new Type[] {
    typeof(Enum),
    typeof(String),
    typeof(Decimal),
    typeof(DateTime),
    typeof(DateTimeOffset),
    typeof(TimeSpan),
    typeof(Guid)
        }.Contains(type) ||
        Convert.GetTypeCode(type) != TypeCode.Object ||
        (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) && IsSimpleType(type.GetGenericArguments()[0]))
        ;
}
public object GetValueOrNull(object obj)
{
    if (obj == null) return null;
    Type objType = obj.GetType();
    PropertyInfo[] properties = objType.GetProperties();
    var simpleTypes = properties.Where(t => IsSimpleType(t.PropertyType));

    var nonValueTypes = properties.Where(p => !simpleTypes.Contains(p));
    foreach (var child in nonValueTypes)
    {
        child.SetValue(obj, GetValueOrNull(child.GetValue(obj)));
    }
    return simpleTypes.All(z => z.GetValue(obj) == null) && nonValueTypes.All(z => z.GetValue(obj) == null) ? null : obj;
}

希望有帮助:)

使用泛型和反射

    public T ConvertToNull<T>(T model) where T : class
    {
        if (model == null) return null;
        Type type = model.GetType();
        PropertyInfo[] properties =  type.GetProperties();

        var valueTypes = properties.Where(p => p.PropertyType.Assembly != type.Assembly);
        var nonValueTypes = properties.Where(p => p.PropertyType.Assembly == type.Assembly);

        foreach (var nonValueType in nonValueTypes)
            nonValueType.SetValue(model, ConvertToNull(nonValueType.GetValue(model)));

        if (valueTypes.All(z => z.GetValue(model) == null) && nonValueTypes.All(z => z.GetValue(model) == null))
            return null;
        else
            return model;
    }
public T ConvertToNull(T模型),其中T:class
{
if(model==null)返回null;
Type Type=model.GetType();
PropertyInfo[]properties=type.GetProperties();
var valueTypes=properties.Where(p=>p.PropertyType.Assembly!=type.Assembly);
var nonValueTypes=properties.Where(p=>p.PropertyType.Assembly==type.Assembly);
foreach(非值类型中的var非值类型)
设置值(model,ConvertToNull(nonValueType.GetValue(model));
if(valueTypes.All(z=>z.GetValue(model)==null)和&nonValueTypes.All(z=>z.GetValue(model)==null))
返回null;
其他的
收益模型;
}
在这里你可以叫它

        List<Student> students = new List<Student>();
        Student student = new Student() { Name = "StudentName", Surname = "StudentSurname", Address = new Address() { City = "City", Country = "Country" }, Exam = new Exam() { ExamMark = "ExamMark", ExamName = "ExamName", Teacher = new Teacher() { TeacherName = "TeacherName", TeacherSurname = "TeacherSurname" } } };

        Student student2 = new Student() { Name = "StudentName", Surname = "StudentSurname", Address = new Address(), Exam = new Exam() { ExamMark = "ExamMark", ExamName = "ExamName", Teacher = new Teacher() } };

        students.Add(student);
        students.Add(student2);

        List<Student> results = new List<Student>();
        foreach (var item in students)
        {
            var result = ConvertToNull(item);
            results.Add(result);
        }
List students=newlist();
学生=新学生(){Name=“StudentName”,姓氏=“Student姓氏”,地址=新地址(){City=“City”,Country=“Country”},考试=新考试(){ExamMark=“ExamMark”,ExamName=“ExamName”,Teacher=新教师(){TeacherName=“TeacherName”,TeacherName=“Teacher姓氏”};
学生2=新学生(){Name=“StudentName”,姓氏=“Student姓氏”,地址=新地址(),考试=新考试(){ExamMark=“ExamMark”,ExamName=“ExamName”,教师=新教师()};
学生。添加(学生);
学生。添加(学生2);
列表结果=新列表();
foreach(学生中的var项目)
{
var结果=兑换券(项目);
结果。添加(结果);
}

使用泛型和反射

    public T ConvertToNull<T>(T model) where T : class
    {
        if (model == null) return null;
        Type type = model.GetType();
        PropertyInfo[] properties =  type.GetProperties();

        var valueTypes = properties.Where(p => p.PropertyType.Assembly != type.Assembly);
        var nonValueTypes = properties.Where(p => p.PropertyType.Assembly == type.Assembly);

        foreach (var nonValueType in nonValueTypes)
            nonValueType.SetValue(model, ConvertToNull(nonValueType.GetValue(model)));

        if (valueTypes.All(z => z.GetValue(model) == null) && nonValueTypes.All(z => z.GetValue(model) == null))
            return null;
        else
            return model;
    }
public T ConvertToNull(T模型),其中T:class
{
if(model==null)返回null;
Type Type=model.GetType();
PropertyInfo[]properties=type.GetProperties();
var valueTypes=properties.Where(p=>p.PropertyType.Assembly!=type.Assembly);
var nonValueTypes=properties.Where(p=>p.PropertyType.Assembly==type.Assembly);
foreach(非值类型中的var非值类型)