我想编写一个函数,该函数可以转换对象的所有属性和子属性。而且,如果一个属性的所有属性都为null,那么我将该属性设置为null。我将举一个例子来解释。
例如,如果TeacherName
和TeacherSurname
都为空,那么我想将Teacher
设置为空。然后,如果ExamMark
和ExamName
和Teacher
为空,则Exam
将为空。
您可以从此链接Json Version看到类似我的问题的json版本
public class Student
{
public string Name { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
public Exam Exam { get; set; }
}
public class Exam
{
public string ExamMark { get; set; }
public string ExamName { get; set; }
public Teacher Teacher { get; set; }
}
public class Teacher
{
public string TeacherName { get; set; }
public string TeacherSurname { get; set; }
}
public class Address
{
public string Country { get; set; }
public string City { get; set; }
}
我写了这种方法。但这只是第一步。但是我需要递归的孩子上课。如何将这种方法转换为递归?
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;
}
答案 0 :(得分:2)
使用泛型和反射。
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;
}
在这里您可以调用它
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);
}
答案 1 :(得分:1)
您要的实际上是一种反模式。这是在代码中传播大量空检查的要求。您不仅需要检查所有属性是否为null,而且还必须在要使用它时检查对象是否为null。另外,反射速度非常慢,如果您经常这样做,则会使应用程序陷入困境。
您应该查看Null Object Pattern。它基本上完成了您想要的操作,并且删除了所有那些讨厌的null检查:
public class Student
{
public string Name { get; set; }
public string Surname { get; set; }
public Address Address { get; set; }
public Exam Exam { get; set; }
public static Student NullStudent { get; } = new Student
{
Name = null,
Surname = null,
Address = Address.NullAddress,
Exam = Exam.NullExam,
}
}
您可以对代码中以此方式起作用的每个对象执行此操作(您也可以看到我也对嵌套的Address和Exam类型执行了此操作),然后不要这样做:
if (Student.EverythingIsNull) { Student = null }
if (Student is null) { //do null stuff }
您可以这样做:
if (item == Student.NullStudent) { //do null stuff }
这将导致代码更清晰,您的意图更加突出,并且您可以在每个对象中专门定义什么构成null。
答案 2 :(得分:1)
看看这个GetValueOrNull应该可以工作并做您需要的事情,没有对所有可能的用例进行测试,但是如果不能在所有情况下都不起作用,则可能需要进行一些调整
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;
}
称呼它
var student = new Student { Address = new Address { }, Exam = new Exam { Teacher = new Teacher() } };
var test = GetValueOrNull(student);
希望它会有所帮助:)