Установите Object null, если все его свойства равны NULL в C # - PullRequest
0 голосов
/ 12 декабря 2018

Я хочу написать функцию, которая превращает все свойства и дочерние свойства объекта.И если все свойства одного свойства равны NULL, тогда я установлю это свойство как NULL.Я объясню на одном примере.

Например, если оба значения TeacherName и TeacherSurname равны нулю, тогда я хочу установить Teacher на ноль.Тогда, если ExamMark и ExamName и Teacher равны нулю, то Exam будет нулевым.

Вы можете увидеть json-версию моего вопроса по этой ссылке Json Version

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

Ответы [ 3 ]

0 голосов
/ 12 декабря 2018

Посмотрите на это. 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);

надеюсь, это поможет:)

0 голосов
/ 13 декабря 2018

с использованием Обобщения и Отражения.

    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);
        }
0 голосов
/ 12 декабря 2018

То, что вы просите, на самом деле является анти-паттерном.Что он делает, так это распространяет требование на тонны нулевых проверок в вашем коде.Вы должны не только проверить, все ли свойства имеют значение null, но также проверить, является ли ваш объект нулевым, когда вы хотите его использовать.Также рефлексия очень медленная, и если вы будете делать это часто, вы застрянете в своем приложении.

Вам следует взглянуть на Null Object Pattern .Это в основном делает то, что вы хотите, и вы удаляете все эти надоедливые проверки на нуль:

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,
    }
}

Вы можете сделать это для каждого объекта в вашем коде, который действует таким образом (вы можете видеть, что я сделал это наваши вложенные адреса и типы экзамена), а затем вместо этого:

if (Student.EverythingIsNull) { Student = null }
if (Student is null) { //do null stuff }

Вы можете сделать это:

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

Это приводит к более четкому коду, ваше намерение выделяется большеи вы можете специально определить в каждом объекте, что составляет нуль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...