Как правильно разнести Событие по разным файлам?

133
19 июня 2021, 15:30

Есть статический Класс который выполняет определенный набор действий и информирует через события о ходе свой работы тех кто подписан на него. Этот класс не зависит от других классов, кроме того в котором объявлены EventArg. Таких классов несколько и они разбиты на отдельные dll.

public static class OperatoinManager
    {
        // Событие возникающее при ошибки
        public static event Action<ProcessingEventArgs> ErrorHappend;
        // Информационное событие, возникающее при работе программы
        public static event Action<ProcessingEventArgs> Done;
        // Тайминговое событие, возникающее при работе программы
        public static event Action<TimingArgs> TimingEvent;

        public static void Execute(Document doc, IEnumerable<Element> firstSet, IEnumerable<Element> secondSet, Operation op)
        {
            using (Transaction tx = new Transaction(doc))
            {
                Stopwatch watch_cmd = new Stopwatch();
                tx.Start($"Batch {op}");
                int i = 0;
                foreach (var firstElement in firstSet)
                {
                    foreach (var secondElement in secondSet)
                    {
                        try
                        {
                            ...
                        }
                            Done?.Invoke(new ProcessingEventArgs(new List<Element> { firstElement, secondElement }, $"{op} Done!"));
                            ++i;
                        }
                        catch (Exception ex)
                        {
                            ErrorHappend?.Invoke(new ProcessingEventArgs(new List<Element> { firstElement, secondElement }, ex.Message));
                            continue;
                        }
                    }
                }
                tx.Commit();
                TimingEvent?.Invoke(new TimingArgs(op.ToString(), watch_cmd ));
            }
        }
    }

Есть нестатический класс (VievModel для формы) через который в WPF окне отображается инфа по ходу исполнения программы. Этот класс так же не зависим от других , кроме того в котором объявлены EventArgs. Он идет как отдельная dll, которой может не быть.


    public class ViewModelDockablePanelLogger : DependencyObject
    {
        public ViewModelDockablePanelLogger()
        {
        }
        public string LogInfo
        {
            get { return (string)GetValue(LogInfoProperty); }
            set { SetValue(LogInfoProperty, value); }
        }
        // Using a DependencyProperty as the backing store for LogInfo.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LogInfoProperty =
            DependencyProperty.Register("LogInfo", typeof(string), typeof(ViewModelDockablePanelLogger), new PropertyMetadata(""));

        public string ErrorInfo
        {
            get { return (string)GetValue(ErrorInfoProperty); }
            set { SetValue(ErrorInfoProperty, value); }
        }
        // Using a DependencyProperty as the backing store for ErrorInfo.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ErrorInfoProperty =
            DependencyProperty.Register("ErrorInfo", typeof(string), typeof(ViewModelDockablePanelLogger), new PropertyMetadata(""));

        public string TimingInfo
        {
            get { return (string)GetValue(TimingInfoProperty); }
            set { SetValue(TimingInfoProperty, value); }
        }
        // Using a DependencyProperty as the backing store for TimingInfo.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TimingInfoProperty =
            DependencyProperty.Register("TimingInfo", typeof(string), typeof(ViewModelDockablePanelLogger), new PropertyMetadata(""));

        public void OnDone(ProcessingEventArgs eventArgs)
        {
            LogInfo = LogInfo.Insert(0, $"Elements: {eventArgs.Elements[0].Id}, {eventArgs.Elements[1].Id}, {eventArgs.Message}\n");
        }
        public void OnErrorHappened(ProcessingEventArgs eventArgs)
        {
            ErrorInfo = ErrorInfo.Insert(0, $"{eventArgs.Elements[0].Id}, {eventArgs.Elements[1].Id}, {eventArgs.Message}.\n\n");
        }
        public void OnTimingEvent(TimingArgs eventArgs)
        {
            TimingInfo = $"{eventArgs.Operation} processing time {eventArgs.Watch.ElapsedMilliseconds} ms.\n";
        }
    }

Есть класс в котором находится точка входа, из него происходит вызов всего остального и проверяется наличие dll. Если эта dll найдена, то происходит подписка ViewModel на события.

    public class Ribbon : IExternalApplication
    {
        public Result OnStartup(UIControlledApplication a)
        {
            /// <summary>
            /// Describe paths for all assemblies that include to the project
            /// </summary>
            string pathCurrent = Assembly.GetExecutingAssembly().Location;
            string location = pathCurrent.Substring(0, pathCurrent.LastIndexOf('\\') + 1);
            string pathBatchOperations = location + "DEA.BatchOperations.dll";
            string pathDockPanel = location + "DEA.DockPanel.dll";
            string pathCommonTools = location + "DEA.CommonTools.dll";
            /// <summary>
            /// Create Ribbon tab
            /// </summary>
            string RibbonPanelName = "DEA";
            a.CreateRibbonTab(RibbonPanelName);
            #region Ribbon panel Batch Operations
            /// <summary>
            /// Create Ribbon panel for Batch operations commands
            /// </summary>
            if (File.Exists(pathBatchOperations))
            {
            ....
            }
            #endregion
            #region Ribbon Tab Settings and Dockable Panel
            /// <summary>
            /// Create Ribbon panel for Settings
            /// </summary>
            if (File.Exists(pathDockPanel))
            {
                RibbonPanel SettingsPanel = a.CreateRibbonPanel(RibbonPanelName, "Settings");
                PushButtonData pushButtonHideDockableWindow = new PushButtonData("HideDockable", "Hide Dockable", pathDockPanel, "DEA.DockPanel.Model.ShowHideDockableWindow");
                pushButtonHideDockableWindow.LargeImage = GetImage(Resources.fuckOff.GetHbitmap());
                RibbonItem ri1 = SettingsPanel.AddItem(pushButtonHideDockableWindow);
                MainPage mainPage = new MainPage();
                DockablePaneId paneId = new DockablePaneId(new Guid("4cf41110-46c3-4fd9-a65f-d548201555fd"));
                a.RegisterDockablePane(paneId, RibbonPanelName, (IDockablePaneProvider)mainPage);
                  /// В ЭТОМ МЕСТЕ НУЖНО ВЫПОЛНИТЬ ПОДПИСКУ 
                  /// Что то вроде этого:
                OperatoinManager.Done += ViewModelDockablePanelLogger.OnDone;
                OperatoinManager.ErrorHappend += ViewModelDockablePanelLogger.OnErrorHappened;
                OperatoinManager.TimingEvent += ViewModelDockablePanelLogger.OnTimingEvent;
            }
            #endregion
            return Result.Succeeded;
        }
}

Вопрос в том что нельзя, и наверное, неправильно обратится к экземпляру класса ViewModel из вне. Включать в сборку ссылки на те классы которые генерируют события так же не получится, потому что тогда придется дублировать проверку наличия dll файлов и в классе с окном и в главном классе.

READ ALSO
Binding, создание listBox для Log записей

Binding, создание listBox для Log записей

Пытался сделать ListBox для Log записей в программе

112
Как создать вложенный цикл

Как создать вложенный цикл

Добры день, имею такой код:

104
2 foreign key на одну и туже таблицу

2 foreign key на одну и туже таблицу

Есть в БД сущность Package, хочу также хранить дубликаты этой сущности

115
Заполнить массив элементами из Enum

Заполнить массив элементами из Enum

Подскажите, нужно заполнить массив, не где не могу найти как работать толково с типом enum

91