diff --git a/.github/workflows/uniffi.yaml b/.github/workflows/uniffi.yaml
index b4193941..fa231c2b 100644
--- a/.github/workflows/uniffi.yaml
+++ b/.github/workflows/uniffi.yaml
@@ -137,6 +137,62 @@ jobs:
run: ./gradlew publishMavenKotlinPublicationToCentralPortal publishMavenJavaPublicationToCentralPortal
+ release-csharp:
+ runs-on: ubuntu-latest
+ needs: [ build ]
+ if: "startsWith(github.event.head_commit.message, 'chore(release): publish uniffi')"
+ defaults:
+ run:
+ working-directory: ${{ env.UNIFFI_DIRECTORY }}
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Setup .NET SDK
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '8.0.x'
+
+ - name: Setup Rust Toolchain
+ uses: dtolnay/rust-toolchain@stable
+
+ - name: Download all artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: build/generated/resources
+
+ - name: Move artifacts
+ run: mv ../../build ./
+
+ - name: Install uniffi-bindgen-cs
+ run: cargo install uniffi-bindgen-cs --git https://github.com/aspect-build/uniffi-bindgen-cs --tag v0.10.0+v0.29.4
+
+ - name: Generate C# bindings
+ run: |
+ uniffi-bindgen-cs \
+ --library build/generated/resources/darwin-x86-64/libzen_uniffi.dylib \
+ --out-dir build/generated/csharp
+
+ - name: Fix async callback interfaces
+ run: bash scripts/fix-csharp-bindings.sh build/generated/csharp/zen_uniffi.cs
+
+ - name: Extract version from Cargo.toml
+ id: version
+ run: |
+ VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
+ echo "VERSION=$VERSION" >> $GITHUB_ENV
+ echo "Detected version: $VERSION"
+
+ - name: Pack NuGet package
+ run: dotnet pack nuget/GoRules.ZenEngine.csproj -c Release -p:Version=$VERSION
+
+ - name: Push to NuGet.org
+ run: |
+ dotnet nuget push nuget/bin/Release/*.nupkg \
+ --api-key ${{ secrets.NUGET_API_KEY }} \
+ --source https://api.nuget.org/v3/index.json \
+ --skip-duplicate
+
build-ios:
if: "!contains(github.event.head_commit.message, 'skip ci')"
env:
diff --git a/bindings/uniffi/.gitignore b/bindings/uniffi/.gitignore
index 6eb8b6a7..dd20902a 100644
--- a/bindings/uniffi/.gitignore
+++ b/bindings/uniffi/.gitignore
@@ -1,3 +1,5 @@
.idea
.gradle
build/
+build-android/
+jniLibs/
\ No newline at end of file
diff --git a/bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs b/bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs
new file mode 100644
index 00000000..d63fc8d6
--- /dev/null
+++ b/bindings/uniffi/lib/csharp/GoRules/ZenEngine/JsonBuffer.cs
@@ -0,0 +1,23 @@
+namespace GoRules.ZenEngine;
+
+using System.Text;
+
+public class JsonBuffer
+{
+ public byte[] Value { get; }
+
+ public JsonBuffer(byte[] value)
+ {
+ Value = value;
+ }
+
+ public JsonBuffer(string json)
+ {
+ Value = Encoding.UTF8.GetBytes(json);
+ }
+
+ public override string ToString()
+ {
+ return Encoding.UTF8.GetString(Value);
+ }
+}
diff --git a/bindings/uniffi/nuget/GoRules.ZenEngine.csproj b/bindings/uniffi/nuget/GoRules.ZenEngine.csproj
new file mode 100644
index 00000000..3c9b0d27
--- /dev/null
+++ b/bindings/uniffi/nuget/GoRules.ZenEngine.csproj
@@ -0,0 +1,58 @@
+
+
+
+ net8.0
+ GoRules.ZenEngine
+ GoRules
+ ZEN Engine - Business Rules Engine for .NET. Execute JSON Decision Models (JDM) with native performance via Rust FFI bindings.
+ MIT
+ https://github.com/gorules/zen
+ https://github.com/gorules/zen
+ rules-engine;business-rules;decision-engine;jdm;gorules
+ enable
+ enable
+ true
+ true
+ $(NoWarn);CS1591
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bindings/uniffi/scripts/fix-csharp-bindings.sh b/bindings/uniffi/scripts/fix-csharp-bindings.sh
new file mode 100755
index 00000000..fd164418
--- /dev/null
+++ b/bindings/uniffi/scripts/fix-csharp-bindings.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+#
+# fix-csharp-bindings.sh
+#
+# Fixes the async callback interface bug in C# bindings generated by uniffi-bindgen-cs.
+#
+# The generator produces sync interface methods (returning T directly) but the
+# calling code uses await + .WaitAsync(), causing compilation errors. This script
+# patches the interface method signatures to return Task instead.
+#
+# Usage: ./fix-csharp-bindings.sh
+
+set -euo pipefail
+
+if [ $# -ne 1 ]; then
+ echo "Usage: $0 "
+ exit 1
+fi
+
+FILE="$1"
+
+if [ ! -f "$FILE" ]; then
+ echo "Error: File not found: $FILE"
+ exit 1
+fi
+
+echo "Fixing async callback interfaces in $FILE..."
+
+# Fix ZenCustomNodeCallback.Handle: sync → async (Task<>)
+sed -i.bak 's/ZenEngineHandlerResponse Handle(ZenEngineHandlerRequest @key)/Task Handle(ZenEngineHandlerRequest @key)/' "$FILE"
+
+# Fix ZenDecisionLoaderCallback.Load: sync → async (Task<>)
+sed -i.bak 's/JsonBuffer? Load(string @key)/Task Load(string @key)/' "$FILE"
+
+# Clean up backup file
+rm -f "${FILE}.bak"
+
+echo "Done. Fixed async interfaces in $FILE"