SAL.Windows
1.2.11
dotnet add package SAL.Windows --version 1.2.11
NuGet\Install-Package SAL.Windows -Version 1.2.11
<PackageReference Include="SAL.Windows" Version="1.2.11" />
<PackageVersion Include="SAL.Windows" Version="1.2.11" />
<PackageReference Include="SAL.Windows" />
paket add SAL.Windows --version 1.2.11
#r "nuget: SAL.Windows, 1.2.11"
#:package SAL.Windows@1.2.11
#addin nuget:?package=SAL.Windows&version=1.2.11
#tool nuget:?package=SAL.Windows&version=1.2.11
SAL.Windows
SAL.Windows is a .NET library that provides a plugin-based architecture for developing extensible Windows Forms applications. It's part of the SAL (Software Abstraction Layer) framework that enables modular and flexible application development.
Features
- Plugin-based Architecture: Build applications using modular, reusable plugins
- Multiple UI Support: Works with various interface types (MDI/SDI/Dialog/VS IDE integration)
- Centralized Settings Management: Flexible storage of user settings and configurations
- Dynamic Module Loading: Load required modules based on user roles or server requirements
- Interface Abstraction: Common interfaces for Windows Forms controls and menus
- Cross-platform Compatibility: Supports .NET Framework 3.5 and .NET Standard 2.0
Architecture Overview
The SAL architecture consists of three main components:
- Application Host: The main application that implements one of the supported interfaces
- SAL Host: Core component managing plugin communication and loading
- Plugins: Modular components that provide specific functionality
Plugin System
The architecture is built around the IPlugin interface, allowing plugins to:
- Extend or use other modules
- Access code from other plugins without recompilation
- Save and restore control states between sessions
- Integrate easily with existing applications
- Use standard WinForms UserControl or WPF components
Host Types
SAL supports multiple host types:
- MDI Applications
- Dialog-based Applications
- Visual Studio Integration (EnvDTE)
- Windows Services
- ASP.NET Applications
Getting Started
Basic Plugin Implementation
public class Plugin : IPlugin, IPluginSettings<PluginSettings>
{
private readonly IHost _host;
private PluginSettings _settings;
public Plugin(IHost host)
{
_host = host;
}
public PluginSettings Settings
{
get
{
if(_settings == null)
{
_settings = new PluginSettings(this);
_host.Plugins.Settings(this).LoadAssemblyParameters(_settings);
}
return _settings;
}
}
}
Adding UI Elements
IHostWindows host = this.Host as IHostWindows;
if(host != null)
{
IMenuItem menuTools = host.MainMenu.FindMenuItem("Tools");
if(menuTools != null)
{
var newMenuItem = menuTools.Create("New Feature");
newMenuItem.Name = "tsmiToolsNewFeature";
newMenuItem.Click += OnNewFeatureClick;
menuTools.Items.Insert(0, newMenuItem);
}
}
Creating Windows
IWindow window = hostWindows.Windows.CreateWindow(
plugin: this,
formType: typeof(MyUserControl).ToString(),
searchForOpened: false,
showHint: DockState.DockLeft
);
Adding menus and toolbars
public class MyPlugin : IPlugin
{
private IMenuItem _pluginMenuItem;
internal IHost Host { get; }
/// <summary>It's allowed to launch the plugin with any host, and at startup - the plugin decides how to start</summary>
public MyPlugin(IHost host)
=> this.Host = host;
Boolean IPlugin.OnConnection(ConnectMode mode)
{
IHostWindows host = this.Host as IHostWindows;
if(host != null)
{
IMenuItem menuTools = host.MainMenu.FindMenuItem("Tools");
if(menuTools != null)
{
_pluginMenuItem = menuTools.Create("Menu Item Name");
_pluginMenuItem.Name = "tsmiToolsPluginMenuItem";
_pluginMenuItem.Click += new EventHandler(_pluginMenuItem_Click);
menuTools.Items.Insert(0, _pluginMenuItem);
return true;
}
}
return false;
}
Boolean IPlugin.OnDisconnection(DisconnectMode mode)
{
if(this._pluginMenuItem != null)
this.HostWindows.MainMenu.Items.Remove(this._pluginMenuItem);
return true;
}
}
Opening window (UI should be inherited from UserControl class)
public class MyPlugin : IPlugin
{
private IHostWindows HostWindows { get; private set; }
/// <summary>Creating an instance of this plugin is only possible in a host that implements the IHostWindows interface (Constructor is optional and works as IoC)</summary>
public MyPlugin(IHostWindows host)
=> this.HostWindows = host;
Boolean IPlugin.OnConnection(ConnectMode mode)
{
this.HostWindows.Plugins.PluginsLoaded += (sender, e) => this.CreateWindow(typeof(PanelMyWindowControl).ToString(), true);
return true;
}
Boolean IPlugin.OnDisconnection(DisconnectMode mode)
=> true;
private IWindow CreateWindow(String typeName, Boolean searchForOpened, Object args = null)
=> this.HostWindows.Windows.CreateWindow(this, typeName, searchForOpened, DockState.DockLeft, args);
}
Receiving objects IWindow and IPlugin in the opened window.
public partial class PanelMyWindowControl : UserControl
{
private IWindow Window { get { return (IWindow)base.Parent; } }
private MyPlugin Plugin { get { return (MyPlugin)this.Window.Plugin; } }
protected override void OnCreateControl()
{
this.Window.Caption = "I want cookie";
base.OnCreateControl();
}
}
Core Components
SAL.Flatbed
- Base assembly containing core interfaces
- Minimal set of abstractions for plugins and hosts
- Platform-independent functionality
SAL.Windows
- Windows Forms and WPF specific implementation
- UI component interfaces
- Menu and toolbar abstractions
- Window management
Plugin Architecture
Plugin Lifecycle
- Loading: Plugins are discovered and loaded from configured locations
- Provider Resolution: Settings and plugin providers are initialized
- Kernel Plugin Detection: System identifies and initializes kernel plugins
- Plugin Initialization: Remaining plugins are initialized with dependencies
Plugin Communication
- Inter-plugin communication through public methods, properties, and events
- Host communication via
IHostinterface and its extensions - Settings management through
IPluginSettingsinterface
Configuration
Settings Management
// Loading data
using(Stream stream = plugin.Host.Plugins.Settings(plugin).LoadAssemblyBlob("config.xml"))
{
if(stream != null)
// Process configuration
}
// Saving data
using(MemoryStream stream = new MemoryStream())
{
// Write configuration
plugin.Host.Plugins.Settings(plugin).SaveAssemblyBlob("config.xml", stream);
}
Compatibility
- .NET Framework 3.5
- .NET Standard 2.0
Contributing
Contributions are welcome. Please ensure your changes maintain compatibility with the supported .NET versions.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net35 is compatible. net40 was computed. net403 was computed. net45 was computed. net451 was computed. net452 was computed. net46 was computed. net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 3.5
- SAL.Flatbed (>= 1.2.11)
-
.NETStandard 2.0
- SAL.Flatbed (>= 1.2.11)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.