Гайд Реализация EventController'a

Пользователь
Статус
Оффлайн
Регистрация
1 Апр 2020
Сообщения
91
Реакции[?]
105
Поинты[?]
0
Всем любителям C# привет! В сегодняшнем гайде я бы хотел показать, как реализовать события, которые будут реализовываться в своем собственном классе, но при этом ни одна часть программы не будет вызывать этот класс, тем самым он станет автоматически вызываемым при соблюдении своих условий.

Для этого я создал интерфейс IEventController
C#:
public interface IEventController
    {
        bool CanExecute();

        void Execute();
    }
Реализуем данный интерфейс

C#:
    class Event1 : IEventController
    {
        public virtual bool CanExecute()
        {
            var t = Console.In.ReadLine();

            if (t == "Привет!")
            {
                return true;
            }

            return false;
        }

        public void Execute()
        {
            Console.WriteLine("Здарова! Я событие под номером 1");
        }
    }

    class Event2 : IEventController
    {
        public virtual bool CanExecute()
        {
            var t = Console.In.ReadLine();

            if (t == "Привет, а ты кто?")
            {
                return true;
            }

            return false;
        }

        public void Execute()
        {
            Console.WriteLine("Привет! А я событие номер 2");
        }
    }
После реализации данных классов нам нужно сделать класс-обработчик событий

C#:
internal class ClassEventInfo
    {
        public object SelectedClass { get; set; }

        public Task EventTask { get; set; }

        public Action EventAction { get; set; }
    }

    public static class EventExecutor
    {
        private static bool IsRuned = false;
        private static Thread m_EventTask = new Thread(ExecuteEvent);
        private static Dictionary<Type, ClassEventInfo> m_ClassesInstance;

        public static void StartCore()
        {
            if (IsRuned)
            {
                return;
            }

            m_EventTask.Start();
        }

        public static void StopCore()
        {
            IsRuned = false;

            m_EventTask.Abort();
        }

        private static void ExecuteEvent()
        {
            IEnumerable<Type> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(assembly => assembly.GetTypes().Where(type => type.GetInterface(nameof(IEventController)) != null));

            if(types is null)
            {
                return;
            }

            m_ClassesInstance = new Dictionary<Type, ClassEventInfo>();

            while (true)
            {
                foreach (Type currentClass in types)
                {
                    if (!m_ClassesInstance.TryGetValue(currentClass, out ClassEventInfo selectedClass))
                    {
                        object newInstance = Activator.CreateInstance(currentClass);

                        ClassEventInfo newEventInfo = new ClassEventInfo()
                        {
                            SelectedClass = newInstance,
                            EventAction = () =>
                            {
                                if ((bool)currentClass.GetMethod("CanExecute").Invoke(newInstance, null))
                                {
                                    currentClass.GetMethod("Execute").Invoke(newInstance, null);
                                }
                            }
                        };

                        m_ClassesInstance.Add(currentClass, newEventInfo);

                        selectedClass = newEventInfo;
                    }

                    if(selectedClass.EventTask is null || selectedClass.EventTask.Status != TaskStatus.Running)
                    {
                        selectedClass.EventTask = Task.Factory.StartNew(selectedClass.EventAction);
                    }
                }
            }
        }
    }
Данный класс находит все типы, в которых присутствует реализация IEventController. После реализации данного класса мы переходим в наш метод Main, в котором мы и будем запускать ядро обработчика событий.

C#:
static void Main(string[] args)
        {
            Console.WriteLine("Тестовое приложение!");
            EventExecutor.StartCore();
        }
После всех выше изложенных действий, мы можем запустить код и получить на выходе вот это
Снимок.PNG

Я считаю, что данный пример обработчика событий поможет разделить модель проекта на основной код и класс событий, которые работают самостоятельно без вмешательства в основные строчки кода проекта, а так же способствуют более чистому написанию кода без всяких излишек сишарповских Event'ов
 
Сверху Снизу