NonVisual Plugins (.NET 5+)

This article describes how to create a new .NET 5 non visual plugin.

Getting Started

The Hydra plugin project consists of three parts:

  • Plugin Module - A Class Library project that acts as a container for the module controller and can hold a set of plugins.
  • Module Controller - Entry point of the module. The module controller supplies the host with information about stored plugins and provides methods that allow the host to instantiate and work with plugins.
  • Plugins - Special classes that are stored inside the plugin module.

Creating a project

First a new Class Library project should be createsd using the default Visual Studio Class Library template.

The newly created project requires some fine-tuning to enable features required by the Hydra framework.

Right-click the project file in the Solution Explorer and select option Edit Project File

The default project file is defined as

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

</Project>

The project file needs to be changed to

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0-windows</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <PlatformTarget>x86</PlatformTarget>
    <EnableComHosting>true</EnableComHosting>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  </PropertyGroup>

</Project>

The changes above do the following:

  • <TargetFramework>net5.0-windows</TargetFramework> - sets the target platform to Windows
  • <PlatformTarget>x86</PlatformTarget> - sets the target platform to 32 bit. It should match the corrsponding setting of the host application
  • <UseWindowsForms>true</UseWindowsForms> - adds support of Windows Forms to the project
  • <EnableComHosting>true</EnableComHosting> - enables support of COM interop in the resulting assembly
  • <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> - Forces NuGet references to be copied to the build output. Similar to the Copy Local option afailable for referenced assemblies.

As the last step add reference to the Hydra NuGet package to the project:

Please note that Hydra uses custom package source named 'RemObjects Software'

Module Controller

Module controller is the root of the plugin library. Add a new Hydra Module Controller to the project:

Add Guid and ComVisible attributes to the Module Controller class. These attributes will allow plugins to be loaded by Delphi COM host application:

using System.Runtime.InteropServices;
using RemObjects.Hydra;

namespace PluginSample_WinForms
{
    [ModuleController]
    [Guid("AC35EF6B-98C3-4E51-BFD3-388AA168D4CA")]
    [ComVisible(true)]
    public partial class ModuleController1 : ModuleController
    {
        public ModuleController1()
        {
            InitializeComponent();
        }
    }
}

Plugin

Add a new Plugin to the project:

And that's it. No additional registration is required.

Using The Plugin

Non-visual plugin provides a set of events that can be triggered by the host application:

  • OnStart
  • OnStop
  • OnPause
  • OnResume

These events can be triggered from the host by calling the corresponding methods (Start, Stop, etc).

Also plugins can expose thir functionality via custom interfaces. Custom interfaces are user-defined interfaces that can be used in a cross-platform environment (they can, for example, be shared between a .NET plugin and a Delphi host application) to provide access to a host or plugin methods. More details can be found in this article: Passing Interfaces between Host and Plugins.

Custom Plugin Interfaces

Plugins can expose custom interfaces that make interaction with them more flexible.

For example, the following steps are required to expose an interface like this to the host applicaiton:

namespace PluginSample_WinForms
{
    public interface ISum
    {
        int Sum(int a, int b);
    }
}

As a first step the interface should be inhetired from the IHYCrossPlatformInterface interface and some additional attributes should be applied to its definition:

using System.Runtime.InteropServices;
using RemObjects.Hydra.CrossPlatform;

namespace PluginSample_WinForms
{
    [Guid("7270A2DC-AEC4-460F-B652-886068D85592")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface ISum: IHYCrossPlatformInterface
    {
        int Sum(int a, int b);
    }
}

Then the plugin implementation class should implement this interface.

At the Delphi host application corresponding interface definition should look like

  ISum = interface
  ['{7270A2DC-AEC4-460F-B652-886068D85592}']
    function Sum(a,b: Integer): Integer; safecall;
  end;

Then the Host code can access the plugin method as

procedure TMainForm.SumButtonClick(Sender: TObject);
var
  ls: ISum;
begin
  if Supports(Instance, ISUM, ls) then
    ShowMessage(ls.Sum(9, 8).ToString)
  else
    ShowMessage('ISum interface dosn''t supported');
end;

Registering The Plugin

Build the project

The resulting folder should contain plugin assembly, corresponding comhost dll and Hydra assemblies.

The last step is to register the plugin as COM server in the COM infrastrucure.

This can be done using the regsvr32 command:

regsvr32 .\PluginSample_WinForms.comhost.dll

Now this .NET 5-based visual plugin can be loaded by Delphi Hydra host application.