======= 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); }