Aragas/Bannerlord.MBOptionScreen

View on GitHub
src/MCM.Common/Ref/RefWrapper.cs

Summary

Maintainability
A
0 mins
Test Coverage
using HarmonyLib.BUTR.Extensions;

using System;
using System.ComponentModel;

namespace MCM.Common
{
    /// <summary>
    /// Wrapper around any type that implements <see cref="IRef"/>.
    /// We don't use casting because it might not be safe.
    /// </summary>
#if !BANNERLORDMCM_INCLUDE_IN_CODE_COVERAGE
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage, global::System.Diagnostics.DebuggerNonUserCode]
#endif
#if !BANNERLORDMCM_PUBLIC
    internal
#else
    public
# endif
    class RefWrapper : IRef, IWrapper
    {
        private delegate Type GetTypeDelegate();
        private delegate object GetValueDelegate();
        private delegate void SetValueDelegate(object value);

        private readonly GetTypeDelegate? _getTypeDelegate;
        private readonly GetValueDelegate? _getValueDelegate;
        private readonly SetValueDelegate? _setValueDelegate;

        /// <inheritdoc/>
        public object Object { get; }

        /// <inheritdoc/>
        public event PropertyChangedEventHandler? PropertyChanged
        {
            add { if (Object is INotifyPropertyChanged notifyPropertyChanged) notifyPropertyChanged.PropertyChanged += value; }
            remove { if (Object is INotifyPropertyChanged notifyPropertyChanged) notifyPropertyChanged.PropertyChanged -= value; }
        }
        /// <inheritdoc/>
        public Type Type => _getTypeDelegate!.Invoke();
        /// <inheritdoc/>
        public object? Value
        {
            get => _getValueDelegate!.Invoke();
            set
            {
                if (_setValueDelegate is not null && value is not null)
                    _setValueDelegate(value);
            }
        }

        public RefWrapper(object @object)
        {
            Object = @object;
            var type = @object.GetType();

            _getTypeDelegate = AccessTools2.GetPropertyGetterDelegate<GetTypeDelegate>(@object, type, nameof(Type));
            _getValueDelegate = AccessTools2.GetPropertyGetterDelegate<GetValueDelegate>(@object, type, nameof(Value));
            _setValueDelegate = AccessTools2.GetPropertySetterDelegate<SetValueDelegate>(@object, type, nameof(Value));
        }
    }
}