=======
Plugins
=======
XML Configuration file has elements to specify plugins.
Plugins are extensions that allow specifying additional type bindings, plugin specific settings and some other functionality:
.. contents::
:local:
:depth: 2
Adding a Plugin
===============
To add a plugin do the following:
1) Add a child element **plugin** to **iocConfiguration/plugins** and specify the plugin name using the **name** attribute. See the example below:
.. note::
All the types related to plugins should be in assemblies that are in a directory **[plugins directoy]\[plugin name]**, where **[plugins directoy]** is the directory specified in attribute **pluginsDirPath** of element **iocConfiguration/plugins** and **[plugin name]** is the value of attribute **name** of element **iocConfiguration/plugins/plugin**.
.. code-block:: xml
2) Add a child element **pluginSetup** to **iocConfiguration/pluginsSetup** (**iocConfiguration/pluginsSetup** is next to **iocConfiguration/startupActions** element), and make sure to use the same value for **plugin** attribute as the value of attribute **name** in **plugin** element mentioned in step 1).
- Here is an example of **iocConfiguration/pluginsSetup/pluginSetup** element with explanation of some elements in **pluginSetup** element.
.. code-block:: xml
:linenos:
Element **pluginImplementation**
================================
The element **iocConfiguration/pluginsSetup/pluginSetup/pluginImplementation** is used to specify an implementation of interface **IoC.Configuration.IPlugin** for the plugin.
The easiest way to provide an implementation of **IoC.Configuration.IPlugin** is to extend the abstract class **IoC.Configuration.PluginAbstr** and to override the abstract methods **IoC.Configuration.PluginAbstr.Initialize()** and **IoC.Configuration.PluginAbstr.Dispose()**. **PluginAbstr** implements **IoC.Configuration.IPlugin**.
.. note::
Plugins are integrated into dependency injection mechanism. Therefore, the constructor parameters of **IoC.Configuration.IPlugin** implementations specified in **pluginImplementation** elements will be injected using the bindings specified in XML Configuration file or in modules referenced by the configuration file. Also, **parameters** and **injectedProperties** elements can used with **pluginImplementation** element to specify constructor parameters or property injection.
Here is an example of implementation of **IoC.Configuration.IPlugin** interface that is referenced in element **iocConfiguration/pluginsSetup/pluginSetup/pluginImplementation** in example above:
.. code-block:: csharp
public class Plugin1 : IoC.Configuration.PluginAbstr
{
private readonly List _requiredSettings;
public Plugin1(long param1)
{
Property1 = param1;
_requiredSettings = new List();
_requiredSettings.Add(new SettingInfo("Int32Setting1", typeof(int)));
_requiredSettings.Add(new SettingInfo("StringSetting1", typeof(string)));
}
public override IEnumerable RequiredSettings => _requiredSettings;
public override void Dispose()
{
// Dispose resources
}
public override void Initialize()
{
// Do initialization here
}
public long Property1 { get; }
public long Property2 { get; set; }
}
Getting Plugin Data at Runtime
------------------------------
- To access an instance of **IoC.Configuration.IPlugin** for specific plugin, inject type **IoC.Configuration.IPluginDataRepository** (using constructor or property injection), and use the method **IPluginData GetPluginData(string pluginName)** in interface **IoC.Configuration.IPluginDataRepository**.
An example is demonstrated below:
.. code-block:: csharp
public class AccessPluginDataExample
{
public AccessPluginDataExample(IoC.Configuration.IPluginDataRepository pluginDataRepository)
{
var pluginData = pluginRepository.GetPluginData("Plugin1");
Assert.AreEqual(35, pluginData.Property2);
Assert.AreEqual(25,
pluginData.Settings.GetSettingValueOrThrow("Int32Setting1"));
}
}
Element **typeDefinition** in plugin section
=============================================
Element **iocConfiguration/pluginsSetup/pluginSetup/typeDefinitions/typeDefinition** can be used in plugin section to reference types by type alias, the same way this element is used in non-plugin section.
Refer to :doc:`./using-types-in-configuration` for more details on **typeDefinition** element.
Example of **typeDefintion** elements in **pluginSetup** element:
-----------------------------------------------------------------
.. code-block:: xml
:linenos:
Plugin Settings
===============
An element **iocConfiguration/pluginsSetup/pluginSetup/settings** can be used to specify plugin specific settings. The format of plugin settings is similar to settings in general area (i.e., in element **iocConfiguration/settings**). For more details on settings in general refer to :doc:`./settings`.
.. code-block:: xml
Here is an example of how to access plugin setting values at runtime:
.. code-block:: csharp
public class AccessPluginDataExample
{
public AccessPluginDataExample(IoC.Configuration.IPluginDataRepository pluginDataRepository)
{
var pluginData = pluginRepository.GetPluginData("Plugin1");
Assert.AreEqual(25,
pluginData.Settings.GetSettingValueOrThrow("Int32Setting1"));
Assert.AreEqual("String Value 1",
pluginData.Settings.GetSettingValueOrThrow("StringSetting1"));
}
}
- If a setting is not found in plugin settings element **iocConfiguration/pluginsSetup/pluginSetup/settings**, **IoC.Configuration** will search for a setting in general settings area (i.e., in settings defined in element **iocConfiguration/settings**).
- To specify required settings, implement the property **IEnumerable RequiredSettings { get; }** in interface **IoC.Configuration.IPlugin**, or override the virtual property with the same name in **IoC.Configuration.PluginAbstr**, if the plugin implementation is a subclass of **IoC.Configuration.PluginAbstr** class.
Plugin Modules
==============
- Plugin modules can be specified in **module** elements under element **iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/modules**.
- The format of **iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/modules** is similar to the format of element **iocConfiguration/dependencyInjection/modules**, except that plugin modules are used to specify type bindings for plugin related types. See :doc:`./modules` for more details on **iocConfiguration/dependencyInjection/modules** element.
Plugin Type Bindings
====================
Plugin related type binding can be specified either under element **iocConfiguration/dependencyInjection/services** to provide plugin related implementations for non plugin interfaces, or under element **iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/services** for cases when both the service and the implementation are plugin specific.
.. note::
If the plugin is disabled by setting the value of attribute **enabled** in element **iocConfiguration/plugins/plugin** for the specific plugin, the type bindings for the given plugin will be ignored.
Example 1: Plugin Specific Implementation for non Plugin Type
-------------------------------------------------------------
Here is an example of binding a non-plugin service **SharedServices.Interfaces.IInterface5** to plugin specific type **TestPluginAssembly1.Implementations.Interface5_Plugin1Impl**.
.. code-block:: xml
Example 2: Plugin Specific Implementation for Plugin Type
---------------------------------------------------------
Here is an example of binding a plugin service **TestPluginAssembly1.Interfaces.IDoor** to plugin specific type **TestPluginAssembly1.Implementations.Door**.
.. code-block:: xml
Plugin types in **collection** in non-plugin section
====================================================
Plugin types can be used in value initializer elements for specifying items in **collection** element plugin as well as in non-plugin section.
.. note::
Refer to :doc:`./value-initialization-elements/collection` for more details on **collection** element.
.. note::
Refer to :doc:`./value-initialization-elements/index` for more details on value intialization elements.
If value of plugin type is used in a collection item in non-plugin section, and the plugin is disabled by setting the value of attribute **enabled** in element **iocConfiguration/plugins/plugin** for the specific plugin, the item will not be included in a collection generated by **IoC.Configuration**.
Autogenerated Services
======================
An interface with auto-generated implementations can be specified in element **iocConfiguration/pluginsSetup/pluginSetup/dependencyInjection/autoGeneratedServices**. For more information on autogenerated services see :doc:`./autogenerated-services/index`.
Here is an example of **autoGeneratedServices** for a plugin. In this example, **IoC.Configuration** will generate an implementation of **TestPluginAssembly1.Interfaces.IResourceAccessValidatorFactory** and will configure a type binding, that ,apts the interface **IResourceAccessValidatorFactory** to auto-generated type.
.. code-block:: xml
:linenos:
The definition of interface **IResourceAccessValidatorFactory** is shown below
.. code-block:: csharp
public interface IResourceAccessValidatorFactory
{
IEnumerable GetValidators(string resourceName);
}