- Create a presentation layer as a dynamic library. Install the ImageProcessing.Microkernel.EntryPointfrom Nuget. Add an implementation of theIStartupinterface, create folders for presenters/events/views/viewmodels.
- Define a new interface for your main view. It should implement the IViewinterface.
- Create a new presenter for your main view. Inherit it from the BasePresenter<TView>. Create a new domain event and subscribe it to the main presenter with theISubscriber<TEventArgs>interface.
- Create an executing assembly. Reference the presentation library. It can be a console, WPF or WinForms project. Add an implementation of the IStartupinterface for the UI Layer components.
- In case of WF or WPF, create a base form to handle write/read from another thread or access the aggregator or application controller. Create a property for the application controller. Set it with the AppController.Controller. Using theController.IoCproperty register theApplicationContext/Applicationas a singleton then resolve it and bind to theContextproperty. You can do it once via the null reference check with the private field. Hide theShowwith thenewsyntax then set theMainFormasthis. Pass the Context to theApplication.Run.
- Implement the IMainViewinterface for your main form. In case of WF/WPF use theAggregator.Unpublishinside theDispose/Closecall. Hide the generated dispose with thenewsyntax then replace if a view is a transient, or remove it in the case of a singleton, delegating the disposing call to a DI-container.
- Inject the singleton instance of the IEventAggregatorinto your main form or expose elements to a custom event binder component. Bind the defined domain event.
- Register the implemented presentation startup dependecies with the new Startup().Build(builder)inside theUIStartup. Register the main view and its event binder. You can declare the main view as a singleton to inject it to child views and access control properties via the exposer cast.
- Inside the Program class use the static state machine to AppLifecycle.Build<UIStartup>andAppLifecycle.Run<MainPresenter>.
- Use Run<TPresenter>orRun<TPresenter, TViewModel>to run a presenter. When aViewaccessed for the first time, a DI - container resolve the view by its interface, decoupling a concrete implementation of a gui framework (WF, WPF, Console) component.
- Use PublishFrom<TEventArgs>(object publisher, TEventArgs args)to unicast a message from a view to its presenter.
- Use PublishFromAll<TEventArgs>(object publisher, TEventArgs args)to broadcast a message from a view to all presenters subscribed to theTEventArgs. It can also be used to message from a presenter to a presenter if a target presenter have a unique subscriber during the broadcast.
- Use Unsubscribe(Type subscriber, object publisher)to unsubcribe a view from its presenter. Can be used during the disposing of a view.
- Generate or create virtual wrappers around the original components. If a component has a composition with another wrapper, expose its interface as a public property. Extend the original forms with NonUIForms, overriding the write/read methods. Inside a form wrapper create a bridge with a NonUIForm.
- Inside a presenter use the original source code, operating with partial substitutes. Expose substitutes as a public property.
- Extend the SynchronizationContext, override the Post property. Override the Post inside the aggregator, set the extendedSynchronizationContext. Replace the original aggregator with its wrapper..Resultthe.ConfigureAwait(false)calls.
- Using the fluent interface, build the partial substitutes with the virtual wrappers to operate with the original components by default.
- Create a base test, use the static state machine to Buildpartial substitutes and toDisposeon the[TearDown].
- Write a synchronous scenario using partial substitutes. Raise an event from a form wrapper. Use .Receieved()interface to validate arguments and return values.
Fig. 1 - The main MDI - form and child transient forms and the singleton form. The main menu also shows the message from the singleton form.
Fig. 2 - The main form and child SDI transient forms and the singleton form. The main menu also shows the message from the singleton form.
Fig. 3 - The main form and child TDI transient tabs and the singleton tab. The main menu also shows the message from the singleton tab. To close the tab focus the "Send Message" button and press the Del key.
Fig. 4 - The main window and child transient windows and the singleton window. The main window also shows the message from the singleton window.
Fig. 5 - The console window is started with the main command and then the singleton command is switched to a foreground thread.




