Order of events when plugins are initializing

I am seeing that 

Events_BeforeUpdate(UserBeforeUpdateEventArgs e)
is being called before 
SetController(ISqlServerConnectedPlugionController controller)
The event is being setup in the main plugin and the ISqlServerConnectedPlugin is a child of this plugin.

Parents
No Data
Reply
  • Just to confirm the above, here's an unrealistic example of a parent plugin with 2 child plugins, where all 3 implement ISqlServerConnectedPlugin and IConfigurablePlugin.
    using Telligent.Evolution.Extensibility.Configuration.Version1;
    using Telligent.Evolution.Extensibility.Version1;
    using Telligent.Evolution.Extensibility.Version2;
    
    namespace TestPlugins;
    
    public class TestChildPluginB : IPlugin, ISqlServerConnectedPlugin, IConfigurablePlugin
    {
    	public string Name => "Test Child Plugin B";
    
    	public string Description => Name;
    
    	public void Initialize()
    	{
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginB.Initialize");
    
    		PluginManager.AfterInitialization += (sender, args) =>
    			System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginB.AfterInitialization");
    	}
    
    	public void SetController(ISqlServerConnectedPlugionController controller) =>
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginB.SetController");
    
    	public void Update(IPluginConfiguration configuration) =>
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginB.Update");
    
    	public Version Version => new(1, 0, 0, 0);
    	public PropertyGroup[] ConfigurationOptions => [ new() { LabelText = "" } ];
    	public void Install(Version lastInstalledVersion) { }
    	public Task InstallAsync(Version lastInstalledVersion, CancellationToken cancellationToken) => Task.CompletedTask;
    	public void Uninstall() { }
    	public Task UninstallAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
    
    
    public class TestParentPlugin : IPlugin, IPluginGroup, ISqlServerConnectedPlugin, IConfigurablePlugin
    {
    	public string Name => "Test Parent Plugin";
    
    	public string Description => Name;
    
    	public IEnumerable<Type> Plugins => [typeof(TestChildPluginA), typeof(TestChildPluginB)];
    
    	public void Initialize()
    	{
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestParentPlugin.Initialize");
    
    		PluginManager.AfterInitialization += (sender, args) =>
    			System.Diagnostics.Debug.WriteLine("TestPlugins: TestParentPlugin.AfterInitialization");
    	}
    
    	public void SetController(ISqlServerConnectedPlugionController controller) =>
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestParentPlugin.SetController");
    
    	public void Update(IPluginConfiguration configuration) =>
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestParentPlugin.Update");
    
    	public Version Version => new(1, 0, 0, 0);
    	public PropertyGroup[] ConfigurationOptions => [ new() { LabelText = "" } ];
    	public void Install(Version lastInstalledVersion) { }
    	public Task InstallAsync(Version lastInstalledVersion, CancellationToken cancellationToken) => Task.CompletedTask;
    	public void Uninstall() { }
    	public Task UninstallAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
    
    
    public class TestChildPluginA : IPlugin, ISqlServerConnectedPlugin, IConfigurablePlugin
    {
    	public string Name => "Test Child Plugin A";
    
    	public string Description => Name;
    
    	public void Initialize()
    	{
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginA.Initialize");
    
    		PluginManager.AfterInitialization += (sender, args) =>
    			System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginA.AfterInitialization");
    	}
    
    	public void SetController(ISqlServerConnectedPlugionController controller) =>
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginA.SetController");
    
    	public void Update(IPluginConfiguration configuration) =>
    		System.Diagnostics.Debug.WriteLine("TestPlugins: TestChildPluginA.Update");
    
    	public Version Version => new(1, 0, 0, 0);
    	public PropertyGroup[] ConfigurationOptions => [ new() { LabelText = "" } ];
    	public void Install(Version lastInstalledVersion) { }
    	public Task InstallAsync(Version lastInstalledVersion, CancellationToken cancellationToken) => Task.CompletedTask;
    	public void Uninstall() { }
    	public Task UninstallAsync(CancellationToken cancellationToken) => Task.CompletedTask;
    }
    When the parent plugin is enabled, a plugin initialization demonstrates that controllers and configuration are set/injected first on all 3, followed by Initialize() on all 3, followed by AfterInitialization on all 3.
    TestPlugins: TestParentPlugin.SetController
    TestPlugins: TestParentPlugin.Update
    TestPlugins: TestChildPluginA.SetController
    TestPlugins: TestChildPluginA.Update
    TestPlugins: TestChildPluginB.SetController
    TestPlugins: TestChildPluginB.Update
    TestPlugins: TestParentPlugin.Initialize
    TestPlugins: TestChildPluginA.Initialize
    TestPlugins: TestChildPluginB.Initialize
    TestPlugins: TestParentPlugin.AfterInitialization
    TestPlugins: TestChildPluginA.AfterInitialization
    TestPlugins: TestChildPluginB.AfterInitialization
Children
  • Using AfterInitialization does solve the timing issue, so we can use that pattern elsewhere. What was catching me out was that the reference in PluginConnectionStrings had a bad namespace, not sure when that happened but it meant that SetController was never called. The issue here is that the SQL plugin and the Core plugin remained enabled, even though an exception had been thrown that meant they should not be working or enabled.  If an exception is thrown within the main plugin or it's dependent plugins then I think they should all be automatically disabled as they are in an inconsistent state.