@VasyaM13221

Как понять что в объект была добавлена информация, но не изменена существующая?

Доброго времени суток.
Расскажите существует-ли какой то простой способ понять что в объект была добавлена информация но не изменена уже существующая?

Есть объект Customer, у него есть различные поля Name, Age, Addresses[], Jobs[]

Задача в том что бы позволить добавлять новые данные в объект, но запретить изменять уже существующие, например:

class Customer {
	public int Id { get; set; }
	public string Name { get; set; }
	public int Age { get; set; }
	public Address[] Addresses { get; set; }
	public Job[] Jobs { get; set; }


	public void ChangeCustomer() {
		if (Name != null) {
			Name = "Новое имя"; // <- так нельзя
		}

		if (Age == null) {
			Age = 20; // <- так можно
		}
	}
}


Все дело осложняется тем что моя модель customer содержит больше двух десятков полей, некоторые из которых являются массивами.
  • Вопрос задан
  • 206 просмотров
Пригласить эксперта
Ответы на вопрос 3
Zoominger
@Zoominger
System Integrator
Ну так опишите эту логику в set, например, он для того и был придуман.
Ответ написан
Planet_93
@Planet_93
Пример

public class Customer
    {
        private string name;
        private int age;
        public int Id { get; set; }
        public string Name
        {
            set
            {
                if (name != null)
                {
                    Console.WriteLine("Поле уже заполнено " + name);
                }
                else
                {
                    name = value;
                }
            }
            get { return name; }         
        }
        public int Age
        {
            get { return age; }
            set
            {
                if (age != 0)
                {
                    Console.WriteLine("Поле уже заполнено " + age);
                }
                else
                {
                    age = value;
                }
            }
        }
        public Address[] Addresses { get; set; }
        public Job[] Jobs { get; set; }

    }
Ответ написан
Casper-SC
@Casper-SC
Программист (.NET)
Если нужно бросать исключение (я бы бросал). С массивами ты ничего не сделаешь, чтобы нельзя было менять часть массива. Нужно использовать свой тип данных вместо массива, в котором и делать проверки.
using System;

namespace ConsoleApp1
{
    public class ModelBase
    {
        protected bool CheckValueTypeField<T>(T field)
            where T : struct
        {
            return field.Equals(default(T));
        }

        protected bool CheckReferenceTypeField<T>(T field)
            where T : class
        {
            return field == null;
        }

        protected void ThrowIfNotDefault<T>(T field)
            where T : struct
        {
            if (!CheckValueTypeField(field))
            {
                throw new InvalidOperationException();
            }
        }

        protected void ThrowIfNotNull<T>(T field)
            where T : class
        {
            if (!CheckReferenceTypeField(field))
            {
                throw new InvalidOperationException();
            }
        }
    }

    public class TestModel : ModelBase
    {
        private string _name;
        private int _value;

        public string Name
        {
            get { return _name; }
            set
            {
                ThrowIfNotNull(_name);
                _name = value;
            }
        }

        public int Value
        {
            get { return _value; }
            set
            {
                ThrowIfNotDefault(_value);
                _value = value;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var test = new TestModel();
            test.Name = "test name";
            test.Value = 1;

            try
            {
                test.Name = "new name";
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            try
            {
                test.Value = 5;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Display(test);
        }

        static void Display(TestModel model)
        {
            Console.WriteLine(
                $"{nameof(model.Name)} == {model.Name}; {nameof(model.Value)} == {model.Value};");
        }
    }
}


Можно, конечно, и так, но игнорировать изменения и никого об этом не уведомлять так себе затея.
public class TestModel : ModelBase
    {
        private string _name;
        private int _value;

        public string Name
        {
            get { return _name; }
            set
            {
                if (!CheckReferenceTypeField(_name))
                {
                    _name = value;
                }
            }
        }

        public int Value
        {
            get { return _value; }
            set
            {
                if (!CheckValueTypeField(_value))
                {
                    _value = value;
                }
            }
        }
    }


Или такой вариант, пока не определился с поведением, как определишься, можно удалить параметр из конструктора и часть поведения.
using System;

namespace ConsoleApp1
{
    public abstract class ModelBase
    {
        private readonly bool _throwAnExceptionInsteadOfAnEvent;

        public event EventHandler FieldIsNotDefault;

        protected ModelBase(bool throwAnExceptionInsteadOfAnEvent = true)
        {
            _throwAnExceptionInsteadOfAnEvent = throwAnExceptionInsteadOfAnEvent;
        }

        protected bool CheckValueTypeField<T>(T field)
            where T : struct
        {
            return field.Equals(default(T));
        }

        protected bool CheckReferenceTypeField<T>(T field)
            where T : class
        {
            return field == null;
        }

        protected void AssertIsNotDefault<T>(T field)
            where T : struct
        {
            if (!CheckValueTypeField(field))
            {
                if (_throwAnExceptionInsteadOfAnEvent)
                {
                    throw new InvalidOperationException();
                }

                OnFieldIsNotDefault();
            }
        }

        protected void AssertIsNotNull<T>(T field)
            where T : class
        {
            if (!CheckReferenceTypeField(field))
            {
                if (_throwAnExceptionInsteadOfAnEvent)
                {
                    throw new InvalidOperationException();
                }

                OnFieldIsNotDefault();
            }
        }

        protected void OnFieldIsNotDefault()
        {
            FieldIsNotDefault?.Invoke(this, EventArgs.Empty);
        }
    }

    public class TestModel : ModelBase
    {
        private string _name;
        private int _value;

        public string Name
        {
            get { return _name; }
            set
            {
                AssertIsNotNull(_name);
                _name = value;

            }
        }

        public int Value
        {
            get { return _value; }
            set
            {
                AssertIsNotDefault(_value);
                _value = value;
            }
        }

        public TestModel()
            : base(false)
        {
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var test = new TestModel();
            test.FieldIsNotDefault += OnFieldIsNotDefault;
            test.Name = "test name";
            test.Value = 1;

            try
            {
                test.Name = "new name";
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            try
            {
                test.Value = 5;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            test.FieldIsNotDefault -= OnFieldIsNotDefault;
            Display(test);
        }

        private static void OnFieldIsNotDefault(object sender, EventArgs e)
        {
            Console.WriteLine("Поле уже установлено");
        }

        static void Display(TestModel model)
        {
            Console.WriteLine(
                $"{nameof(model.Name)} == {model.Name}; {nameof(model.Value)} == {model.Value};");
        }
    }
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы