Table of Contents

Acuit Pinpoint Server Plug-ins

Acuit Pinpoint Server plug-ins are .NET assemblies that run on the server to provide custom behavior. For example, when a unit is scanned at the end of a line, a plug-in could be used to send that unit's serial number to a separate warehousing system. They are configured via the line configuration to be loaded by Acuit Pinpoint Server as the line is initialized.

See Acuit Pinpoint Plug-ins for general details about Acuit Pinpoint plug-ins.

NuGet Dependencies

The packages necessary for developing Acuit Pinpoint Server plug-ins are published via the NuGet package manager. Various packages related to Acuit Pinpoint are available, but the Acuit.Pinpoint.Server.PlugIns meta package is the only Acuit Pinpoint package reference needed for developing plug-ins for Acuit Pinpoint Server.

Simply add a reference to this package within your Visual Studio project to obtain everything needed to integrate with Acuit Pinpoint Server.

Note

Remember that the version of the Acuit.Pinpoint.Server.PlugIns package that you reference in your project determines the minimum version of Acuit Pinpoint Server that will be required to host your plug-in.

Line Plug-ins

A line plug-in is a type in a .NET assembly that implements the ILinePlugIn interface, which allows it to integrate with the Acuit Pinpoint business logic on the server. See the interface documentation for more information.

Server plug-ins are integrated with Acuit Pinpoint Server via the <plugIns> Element configuration settings.

Plug-in Modules

The first time Acuit Pinpoint Server loads a line plug-in from an assembly located in a particular directory, it will first load and initialize all plug-in modules found in assemblies in that directory, and then retain a reference to the module instance.

When the last line plug-in from any assembly in that directory is unloaded, all plug-in modules loaded will be disposed (if they implement IDisposable) and the reference will be released.

Services

Acuit Pinpoint Server makes the following services available to plug-in modules:

Acuit Pinpoint Server makes the following services available to line plug-ins:

Options

It is recommended to use the .NET options pattern for plug-in options that can be configured via Acuit Pinpoint's key/value configuration settings. (See Acuit Pinpoint Plug-ins for more information.)

For options that apply to an entire plug-in module, dependency injection services should typically be used to configure options. However, for options that are specific to a line plug-in, this is not possible, as the line plug-in is created after the plug-in module service collection has been initialized. To use the .NET options pattern in line plug-ins, create an isolated service collection to configure the options, and then build the service provider for accessing the options.

For example, assume we have the following options classes, which demonstrate nested options that should also be validated and which use the .NET 8+ options validator source generator:

public class LinePlugInOptions
{
    [Required]
    public required string RequiredOption { get; set; }

    [ValidateObjectMembers]
    public NestedOptions Nested { get; } = new();

    [ValidateEnumeratedItems]
    public List<NestedOptions> NestedCollection { get; } = [];
}

[OptionsValidator]
public partial class ValidateLinePlugInOptions : IValidateOptions<LinePlugInOptions> { }

public class NestedOptions
{
    [Range(1, 3)]
    public int RangeOption { get; set; }
}

[OptionsValidator]
public partial class ValidateNestedOptions : IValidateOptions<NestedOptions> { }

The line plug-in class could then do the following to configure and use these options:

public sealed class OptionsPatternIsolatedServicesLinePlugIn : ILinePlugIn, IDisposable
{
    private ServiceProvider? _optionsServiceProvider;
    private IOptionsMonitor<LinePlugInOptions>? _optionsMonitor;

    private IOptionsMonitor<LinePlugInOptions> OptionsMonitor => _optionsMonitor ??
        throw new InvalidOperationException("The plug-in has not been initialized.");

    public void Dispose()
    {
        _optionsServiceProvider?.Dispose();
    }

    public void Initialize(string plugInName, PlugInHostContext hostContext)
    {
        _optionsServiceProvider = new ServiceCollection()
            .Configure<LinePlugInOptions>(hostContext.Configuration.GetSection("LinePlugIn"))
            .AddSingleton<IValidateOptions<LinePlugInOptions>, ValidateLinePlugInOptions>()
            // Could configure additional options here as well
            .BuildServiceProvider();
        _optionsMonitor = _optionsServiceProvider.GetRequiredService<IOptionsMonitor<LinePlugInOptions>>();
    }

    public string? InvokePlugIn(string methodName, string? parameter)
    {
        // This will throw OptionsValidationException when the options are not valid:
        LinePlugInOptions options = OptionsMonitor.CurrentValue;

        return options.RequiredOption;
    }
}