Есть статический Класс который выполняет определенный набор действий и информирует через события о ходе свой работы тех кто подписан на него. Этот класс не зависит от других классов, кроме того в котором объявлены 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 файлов и в классе с окном и в главном классе.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Есть в БД сущность Package, хочу также хранить дубликаты этой сущности
Подскажите, нужно заполнить массив, не где не могу найти как работать толково с типом enum