Package
Table of Contents
- Overview
- Package Downloads
- Package Annotations
- Annotation Reference
- Creating Packages (.NET)
- Publishing Libraries
- Package Management
Overview
The Port package is a collection of reusable libraries designed for modular development. Users can create packages by inheriting from PortObject and link them to Messages, enabling straightforward usage through Message calls.
Port packages provide a standardized way to:
- Create reusable components
- Manage dependencies and configurations
- Enable seamless integration with the Port ecosystem
- Facilitate API-driven interactions
Package Downloads
The following packages are available across different programming languages and platforms:
| NAME | Language | Package Manager | OS | STABLE |
|---|---|---|---|---|
| portdic | C++ | not yet | Windows | No |
| portdic | Delphi | not yet | Windows | No |
| portdic | C# | nuget | Windows | Yes |
| portdic | Python | not yet | Windows | No |
| portdic | Javascript | npm | Any | Yes |
Package Annotations
Port packages use annotations to define behavior, configuration, and API endpoints. These annotations provide metadata that the Port system uses for:
- Class Registration: Identifying Port-managed classes
- API Generation: Creating REST endpoints automatically
- Dependency Injection: Managing services and resources
- Validation: Ensuring data integrity and business rules
Annotation Summary
| Name | Targets | Type | Arguments | Description |
|---|---|---|---|---|
| Port | class | - | Class Type | Declares a class as Port-managed for package registration |
| Valid | method, property | bool | invalid comment | Defines validation logic with custom error messages |
| Entry | property | string, double | - | Creates API endpoints for property access |
| Logger | property | ILogger | - | Enables dependency injection for logging services |
| Property | property | IProperty | - | Maps properties to pre-declared Properties |
| EnumCode | enum | - | - | Exposes enum values through API endpoints |
| Comment | property | - | comment text | Provides API documentation for properties |
Annotation Reference
Valid Annotation
The Valid annotation defines validation logic for methods or properties, with custom error messages for validation failures.
[Valid("Invalid for connection")]
public bool Valid()
{
return true;
}
Usage:
- Applied to methods returning
bool - Provides custom error messages for validation failures
- Automatically called during package validation
Port Annotation
The Port annotation indicates that a class is managed within the Port Package system.
using portpackage;
using portdatatype;
[References(typeof(Heater))]
public class Heater
{
// Implementation
}
Usage:
- Applied to class declarations
- Registers the class with the Port system
- Enables package management and API generation
Logger Annotation
The Logger annotation specifies that a field should be injected with a logging system or service.
using portpackage;
using portdatatype;
[Logger]
public ILogger Logger { get; set; }
// Usage example
Logger.Write(string.Join(",", values));
Usage:
- Applied to
ILoggerproperties - Enables dependency injection for logging
- Provides centralized logging capabilities
Property Annotation
The Property annotation maps a property to declared Message Properties for configuration access.
using portpackage;
using portdatatype;
[Property]
public IProperty Property { get; set; }
// Usage example
if (this.Property.TryToGetValue("Unit", out string value))
{
// Handle configuration value
}
Usage:
- Applied to
IPropertyproperties - Enables access to configuration values
- Supports key-value property retrieval
Entry Annotation
Properties declared with Entry annotation become API endpoints, accessible via REST API.
using portpackage;
using portdatatype;
private static Random r = new Random(100);
[Entry(PortDataType.Num, PropertyFormat.Json, "Unit")]
public double Temp
{
get
{
try
{
if (this.Property != null)
{
if (this.Property.TryToGetValue("Unit", out string v1) && (v1 == "F"))
{
return (r.NextDouble() * 9 / 5) + 32;
}
else if (this.Property.TryToGetValue("Unit", out string v2) && (v2 == "C"))
{
return (r.NextDouble());
}
else
{
return double.NaN;
}
}
return double.NaN;
}
catch (Exception e)
{
if (Logger != null)
Logger.Write(e.Message);
}
return double.NaN;
}
}
Usage:
- Applied to properties with get/set accessors
- Creates REST API endpoints automatically
- Supports various data types and formats
EnumCode Annotation
The EnumCode annotation exposes enum values through API endpoints for external access.
[EnumCode]
public enum TestEnum : ushort
{
_ = 0,
TestEnumItem1,
TestEnumItem2,
}
Usage:
- Applied to enum declarations
- Makes enum values accessible via API
- Enables external systems to query enum information
Comment Annotation
The Comment annotation provides documentation for properties, exposed through the API.
[Entry, Comment("this is a numeric")]
public int NValue { get => 3; }
Usage:
- Applied alongside other annotations
- Provides API documentation
- Enhances developer experience with contextual information
Creating Packages (.NET)
Port applications organize operations at the package level and functionality at the message level. All operations are defined within messages, enabling code reusability through message-based architecture.
Class Library Examples
Bulb Package
using portpackage;
using portdatatype;
[References(typeof(Bulb))]
public class Bulb
{
[Logger]
public ILogger Logger { get; set; }
[Property]
public IProperty Property { get; set; }
private SerialPortStream serialPort = new SerialPortStream();
[Valid("")]
public bool Valid()
{
return true;
}
private string comport;
[Entry(PortDataType.Text)]
public string Comport
{
set
{
try
{
if (this.serialPort.PortName != value)
{
this.serialPort = new SerialPortStream();
this.serialPort.PortName = value.ToString();
this.serialPort.BaudRate = 9600;
this.serialPort.DataBits = 8;
this.serialPort.StopBits = StopBits.One;
this.serialPort.Parity = Parity.Even;
}
}
catch (System.Exception ex)
{
Logger.Write("[ERROR]" + ex.Message);
}
}
get
{
return comport;
}
}
private string offon = string.Empty;
[Entry(PortDataType.Enum, PropertyFormat.Json)]
public string OffOn
{
set
{
var prop = this.Property;
try
{
if (prop != null)
{
this.offon = value;
}
}
catch (Exception ex)
{
Logger.Write("[ERROR]" + ex.Message);
}
}
get
{
return this.offon;
}
}
}
Heater Package
using portpackage;
using portdatatype;
[References(typeof(Heater))]
public class Heater
{
[Logger]
public ILogger Logger { get; set; }
[Property]
public IProperty Property { get; set; }
[Entry(PortDataType.Text)]
public string Power { set; get; }
[Valid("Invalid for connection")]
public bool Valid()
{
return true;
}
private static Random r = new Random(100);
[Entry(PortDataType.Num, PropertyFormat.Json, "Unit")]
public double Temp
{
get
{
try
{
if (this.Property != null)
{
if (this.Property.TryToGetValue("Unit", out string v1) && (v1 == "F"))
{
var ret = (r.NextDouble() * 9 / 5) + 32;
return ret == 0 ? 1 : ret;
}
else if (this.Property.TryToGetValue("Unit", out string v2) && (v2 == "C"))
{
var ret = (r.NextDouble());
return ret == 0 ? 1 : ret;
}
else
{
return double.NaN;
}
}
return double.NaN;
}
catch (Exception e)
{
if (Logger != null)
Logger.Write(e.Message);
}
return double.NaN;
}
}
}
!!! warning "Array Declaration Warning" When creating a library in a .NET environment, declaring an excessively large array may result in a PrivateImplementationDetails error. It is recommended to use a List instead.
Publishing Libraries
Prerequisites
Before publishing your .NET Core project, ensure you have the following:
- .NET SDK: Install the latest version
- C# Extension: Install in Visual Studio Code
- Verified Build: Ensure your project builds and runs correctly:
dotnet build
dotnet run
Basic Publish Commands
Standard Release Build
dotnet publish -c Release -o ./publish
-c Release: Builds in Release mode-o ./publish: Specifies output folder
Platform-Specific Publishing
dotnet publish -c Release -r win-x64 --self-contained false
Available Runtimes:
win-x64: Windows 64-bitlinux-x64: Linux 64-bitosx-x64: macOS 64-bit
Automation with VS Code Tasks
Create .vscode/tasks.json to automate publishing:
{
"version": "2.0.0",
"tasks": [
{
"label": "Publish .NET Core",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"-c",
"Release",
"-o",
"./publish"
],
"problemMatcher": "$msCompile"
}
]
}
To run the task:
- Open Command Palette (
Ctrl+Shift+P) - Select
Tasks: Run Task - Choose
Publish .NET Core
Deployment Options
Local Deployment
Copy published files to target server or hosting environment.
Docker Deployment
Create a Dockerfile for containerization:
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
COPY ./publish .
ENTRYPOINT ["dotnet", "YourApp.dll"]
Visual Studio 2022 Publishing
For GUI-based publishing with Visual Studio 2022:





Troubleshooting
Logging Output
To capture publish logs:
dotnet publish > publish_log.txt
Additional Resources
Package Management
Creating Package Files
After publishing your library, create a Port package using the following steps:
1. Navigate to Publish Directory
cd [Publish target location]
2. Pack the Library
port pack [dllname] [pkg-name]
3. Verify Package Creation
Check the console output for successful packaging:
PS C:\Users\Public\Dev\publish> port pack HeaterLib.dll HeaterLib1
[PATH]C:\Users\Public\Dev\publish\HeaterLib.dll
[ALREADY_RUN]PORT PACKAGE MANAGER
[RUN]PORT PACKAGE MANAGER
[PACK][pack] Packing started at 2025-01-07T21:17:19+09:00
[PACK]load complete C:\Users\Public\Dev\publish\HeaterLib.dll : heaterlib
[PACK][GET][0] Power
[PACK][GET][1] Temp
[PACK][SET][0] Power
[PACK]heaterlib,65025
[PACK]initialization
[CREATED][PACKAGE] ...\port\pkg\HeaterLib1.pkg
Package Structure
The packaging process:
- Analysis: Scans the DLL for Port annotations
- Extraction: Identifies all properties and methods
- Validation: Ensures package integrity
- Creation: Generates
.pkgfile in the Port package directory
Package Installation
Once created, packages can be:
- Loaded into Port applications
- Distributed to other environments
- Managed through the Port Package Manager
- Accessed via REST API endpoints