Port Package Documentation¶
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 |
Message | property | string , double |
- |
Creates API endpoints for property access |
Logger | property | ILogger |
- |
Enables dependency injection for logging services |
Property | property | IProperty |
Message name |
Maps properties to pre-declared Message 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.
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;
[Port(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 ILogger
properties
- 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 IProperty
properties
- Enables access to configuration values
- Supports key-value property retrieval
Message Annotation¶
Properties declared with Message
annotation become API endpoints, accessible via REST API.
using portpackage;
using portdatatype;
private static Random r = new Random(100);
[Message(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.
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.
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;
[Port(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;
[Message(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;
[Message(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;
[Port(typeof(Heater))]
public class Heater
{
[Logger]
public ILogger Logger { get; set; }
[Property]
public IProperty Property { get; set; }
[Message(PortDataType.Text)]
public string Power { set; get; }
[Valid("Invalid for connection")]
public bool Valid()
{
return true;
}
private static Random r = new Random(100);
[Message(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;
}
}
}
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:
Basic Publish Commands¶
Standard Release Build¶
-c Release
: Builds in Release mode-o ./publish
: Specifies output folder
Platform-Specific Publishing¶
Available Runtimes:
- win-x64
: Windows 64-bit
- linux-x64
: Linux 64-bit
- osx-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:
1. Open Command Palette (Ctrl+Shift+P
)
2. Select Tasks: Run Task
3. 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:
Additional Resources¶
Package Management¶
Creating Package Files¶
After publishing your library, create a Port package using the following steps:
1. Navigate to Publish Directory¶
2. Pack the Library¶
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 Message properties and methods
- Validation: Ensures package integrity
- Creation: Generates
.pkg
file 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