lundi 17 juillet 2017

Property as an object

I want to pack standard aspect operations like: value conversion, validation, logging etc in object which semantically behaves like a property. I don't want to use IoC, DI containers and etc. The question is: Is it a good pattern to implement properties as an objects? Below is my solution (it's not ideal, just for example). Is there any open source frameworks with the same approach?

class Program
    {
        static void Main(string[] args)
        {
            Person person = new Person();
            person["Age"].Value = 30;
            person["BankAccountId"].Value = 178259;
            Console.WriteLine(person);
            Console.ReadLine();
        }
    }

    // I use this abstract class to be able to create lists of template
    // classes of different types.
    public abstract class ExtendedProperty : INotifyPropertyChanged
    {
        protected string name;

        public string Name => name;

        public abstract object Value { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    /// <summary>
    ///     The main reason for this class is to pack
    ///     standard operations like conversion, validation and logging 
    ///     in a "property". I don't want to use IoC, DI containers.
    /// </summary>
    /// <typeparam name="T">primitive</typeparam>
    public class ExtendedProperty<T> : ExtendedProperty
        where T : struct
    {
        private readonly bool mutable;
        T _value;

        public ExtendedProperty(string name, bool mutable, T initialValue)
        {
            this.name = name;
            this.mutable = mutable;
            _value = initialValue;
        }

        private void setValue(T value)
        {
            if (mutable)
            {
                {/* possible conversion logic */ }
                {/* possible validation logic */ }
                if (!(_value.Equals(value)))
                {
                    _value = value;
                    {/* possible logging logic */}
                    OnPropertyChanged(nameof(Value));
                }
            }
        }

        private T getValue()
        {
            {/* possible conversion logic */ }
            return _value;
        }

        public override object Value
        {
            get
            {
                return getValue();
            }
            set
            {
                setValue((T)value);
            }
        }

        public void Undo() { /* not implemented yet */ }

        public void Redo() { /* not implemented yet */ }
    }

    public class Person
    {
        private List<ExtendedProperty> extProperties = new List<ExtendedProperty>();

        public Person()
        {
            extProperties.Add(new ExtendedProperty<int>("Age", true, 0));
            extProperties.Add(new ExtendedProperty<int>("BankAccountId", true, 0));
        }

        public ExtendedProperty this[string propertyName]
        {
            get
            {
                ExtendedProperty ret = null;
                foreach (var extendedProperty in extProperties)
                {
                    if (extendedProperty.Name == propertyName)
                    {
                        ret = extendedProperty;
                        break;
                    }
                }
                Debug.Assert(ret != null);
                return ret;
            }
        }

        public override string ToString()
        {
            return $"Age: {this["Age"].Value}, BankAccountId: {this["BankAccountId"].Value}";
        }
    }

Aucun commentaire:

Enregistrer un commentaire