SiLA2.Communication
10.2.2
dotnet add package SiLA2.Communication --version 10.2.2
NuGet\Install-Package SiLA2.Communication -Version 10.2.2
<PackageReference Include="SiLA2.Communication" Version="10.2.2" />
<PackageVersion Include="SiLA2.Communication" Version="10.2.2" />
<PackageReference Include="SiLA2.Communication" />
paket add SiLA2.Communication --version 10.2.2
#r "nuget: SiLA2.Communication, 10.2.2"
#:package SiLA2.Communication@10.2.2
#addin nuget:?package=SiLA2.Communication&version=10.2.2
#tool nuget:?package=SiLA2.Communication&version=10.2.2
SiLA2.Communication
Runtime Dynamic Protobuf Generation for SiLA2 Features
| NuGet Package | SiLA2.Communication on NuGet.org |
| Repository | https://gitlab.com/SiLA2/sila_csharp |
| SiLA Standard | https://sila-standard.com |
| License | MIT |
Overview
SiLA2.Communication is a specialized component of the sila_csharp implementation that enables dynamic gRPC communication with SiLA2 servers using runtime-generated protobuf types. This eliminates the need for compile-time code generation when working with SiLA2 Feature Definition Language (FDL) files.
Key Value Proposition
Standard Approach (Compile-time):
.sila.xml (FDL) → XSLT → .proto → protoc → C# gRPC stubs → Compiled Assembly
Dynamic Approach (Runtime):
.sila.xml (FDL) → Runtime IL Emission → Dynamic Types → Reflection-based gRPC calls
This package is ideal for:
- Universal SiLA2 clients that need to connect to any SiLA2 server without pre-compiling feature definitions
- Runtime feature discovery where features are loaded dynamically from server metadata
- Testing tools that need to interact with multiple SiLA2 features without maintaining separate assemblies
- Development environments where rapid iteration is more important than peak performance
When to Use This vs Standard Approach
| Scenario | Use SiLA2.Communication | Use Standard Approach |
|---|---|---|
| Building a universal SiLA2 client | ✅ Yes | ❌ No |
| Runtime feature loading | ✅ Yes | ❌ No |
| Testing multiple features | ✅ Yes | ⚠️ Optional |
| Production feature implementation | ⚠️ Optional | ✅ Yes (better performance) |
| Static feature set known at compile time | ❌ No | ✅ Yes |
Installation
Install via NuGet Package Manager:
dotnet add package SiLA2.Communication
Or via Package Manager Console:
Install-Package SiLA2.Communication
Requirements
- .NET 10.0+
- SiLA2.Core (automatically installed as dependency)
- protobuf-net 3.2.56+
- protobuf-net.Grpc 1.2.2+
- Grpc.AspNetCore 2.76.0+
Core Concepts
1. Feature Definition Language (FDL) to Protobuf Mapping
SiLA2 features are defined in XML files following the SiLA2 FDL schema. This package analyzes FDL metadata at runtime to generate corresponding protobuf message types:
<Feature>
<Identifier>TemperatureController</Identifier>
<Command>
<Identifier>SetTemperature</Identifier>
<Parameter>
<Identifier>Temperature</Identifier>
<DataType>
<Basic>Real</Basic>
</DataType>
</Parameter>
</Command>
</Feature>
At runtime, this generates a protobuf-compatible type equivalent to:
[ProtoContract]
public class TemperatureController_SetTemperature_DynamicProtobufRequest
{
[ProtoMember(1)]
public Real Temperature { get; set; }
}
2. Runtime IL Emission for Type Generation
The package uses .NET Reflection.Emit to generate types at runtime using IL (Intermediate Language) instructions. This is more efficient than using dynamic or ExpandoObject because it creates actual .NET types that can be serialized by protobuf-net.
Types are cached in a shared ModuleBuilder to avoid duplicate generation and improve performance.
3. Four SiLA2 Operation Patterns
The package supports all SiLA2 communication patterns defined in the standard:
| Pattern | gRPC Pattern | Description | Use Case |
|---|---|---|---|
| Unobservable Property | Unary | Get current value immediately | Device status, configuration values |
| Observable Property | Server Streaming | Subscribe to continuous updates | Temperature monitoring, sensor readings |
| Unobservable Command | Unary | Execute and return result immediately | Set parameter, calibrate sensor |
| Observable Command | Multiple RPCs | Long-running operation with progress tracking | Start pump, run experiment |
Observable Command Flow
Observable commands are the most complex pattern, involving multiple gRPC calls:
- Initiate:
ExecuteObservableCommand()→ ReturnsCommandConfirmationwithCommandExecutionUUID - Monitor Progress: Subscribe to
{Command}_Infostream → ReceivesExecutionInfoupdates - Monitor Intermediate Results (optional): Subscribe to
{Command}_Intermediatestream - Retrieve Result:
GetObservableCommandResult()after command completes
4. SiLA2 Data Type Support
The package handles all SiLA2 data types:
- Basic Types: String, Integer, Real, Boolean, Date, Time, Timestamp, Binary, Any
- Constrained Types: Types with value constraints (min/max, regex patterns)
- List Types: Repeated fields using
Google.Protobuf.Collections.RepeatedField<T> - Structure Types: Nested message types with multiple fields
- Custom Defined Types: Feature-specific types defined in FDL
Architecture & Components
Component Overview
┌─────────────────────────────────────────────────────────────┐
│ Client Application │
└───────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ IDynamicMessageService │
│ - GetUnobservableProperty() │
│ - SubcribeObservableProperty() │
│ - ExecuteUnobservableCommand() │
│ - ExecuteObservableCommand() │
│ - GetObservableCommandResult() │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ IPayloadFactory │ │ protobuf-net │
│ │ │ GrpcClient │
│ - Generates request │ │ │
│ and response │ │ - Reflection-based │
│ types from FDL │ │ method invocation │
└──────────┬──────────┘ └─────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ DynamicProtobufTypeBuilder │
│ - IL Emission-based type generation │
│ - Creates ProtoContract-decorated classes │
│ - Manages type caching in shared ModuleBuilder │
└─────────────────────────────────────────────────────────────┘
DynamicProtobufTypeBuilder
Purpose: Generates .NET types at runtime using IL emission that are compatible with protobuf-net serialization.
Key Features:
- Creates classes decorated with
[ProtoContract]attribute - Generates properties with
[ProtoMember(n)]attributes - Implements proper getter/setter IL instructions
- Caches types in shared
ModuleBuilderto avoid duplicates
Thread Safety: Type building uses a shared ModuleBuilder. The builder checks for existing types before creating new ones, but callers should implement locking if concurrent type generation for the same type name is possible.
PayloadFactory
Purpose: Analyzes SiLA2 FDL metadata to determine the correct .NET types for command parameters and property values.
Key Features:
- Parses FDL XML to extract data type information
- Maps SiLA2 data types to protobuf-net types
- Handles complex types (lists, structures, constraints)
- Generates separate request and response types
- Supports metadata-affected properties (
FCPAffectedByMetadata_*pattern)
Type Naming Convention:
- Commands:
{FeatureIdentifier}_{CommandIdentifier}_DynamicProtobufRequest/Response - Properties:
{FeatureIdentifier}_{PropertyIdentifier}_DynamicProtobufRequest/Response - Intermediate Responses:
{CommandIdentifier}_IntermediateResponses
DynamicMessageService
Purpose: Provides the main API for invoking SiLA2 operations using dynamically-generated types.
Key Features:
- Uses protobuf-net's
GrpcClientfor code-first gRPC - Reflection-based method invocation for generic gRPC calls
- Handles all four SiLA2 operation patterns
- Constructs request messages from dictionaries
- Returns responses as dynamically-typed objects
Performance Consideration: Uses reflection to invoke generic methods, which has overhead compared to compile-time generated stubs. For high-throughput scenarios, consider the standard approach.
ProtobufMarshaller
Purpose: Bridges between gRPC and protobuf-net serialization for dynamic types.
Key Features:
- Provides
Marshaller<T>instances for gRPC transmission - Delegates to
ByteSerializerfor protobuf serialization - Compatible with protobuf-net's serialization requirements
- Supports custom serialization logic via
ByteSerializer<T>
Usage Examples
Setup
All examples assume you have:
- A running SiLA2 server
- The feature definition (.sila.xml file)
- A gRPC channel connected to the server
using SiLA2.Communication.Services;
using SiLA2.Server.Utils;
using Grpc.Net.Client;
// Load feature definition
var feature = FeatureGenerator.ReadFeatureFromFile("TemperatureController-v1_0.sila.xml");
// Create gRPC channel
var channel = GrpcChannel.ForAddress("https://localhost:5001");
// Initialize dynamic message service
var dynamicMessageService = new DynamicMessageService(
new PayloadFactory(new DynamicAssemblyBuilder()));
Example 1: Reading an Unobservable Property
// Read device status (returns immediately)
var response = dynamicMessageService.GetUnobservableProperty(
propertyName: "DeviceStatus",
channel: channel,
feature: feature);
// Extract the value using reflection
var statusProperty = response.GetType().GetProperty("DeviceStatus").GetValue(response, null);
var statusValue = statusProperty.GetType().GetProperty("Value").GetValue(statusProperty, null);
Console.WriteLine($"Device Status: {statusValue}");
Note: The response is a dynamically-typed object. You need to use reflection to extract property values, or cast to the appropriate SiLA2 basic type if known.
Example 2: Subscribing to an Observable Property
// Subscribe to continuous temperature updates
var temperatureStream = dynamicMessageService.SubcribeObservableProperty(
propertyName: "CurrentTemperature",
channel: channel,
feature: feature);
// Process streaming updates
await foreach (var update in temperatureStream)
{
var tempProperty = update.GetType().GetProperty("CurrentTemperature").GetValue(update, null);
var tempValue = ((Sila2.Org.Silastandard.Protobuf.Real)tempProperty).Value;
Console.WriteLine($"Temperature: {tempValue}°C");
// Cancel subscription after some condition
if (tempValue > 100.0)
break;
}
Cancellation: Use a CancellationToken in the foreach loop or break to stop receiving updates.
Example 3: Executing an Unobservable Command
using Sila2.Org.Silastandard.Protobuf;
// Prepare command parameters
var parameters = new Dictionary<string, object>
{
{ "Temperature", new Real { Value = 25.5 } },
{ "Unit", new String { Value = "Celsius" } }
};
// Execute command (returns immediately)
var response = dynamicMessageService.ExecuteUnobservableCommand(
operationName: "SetTemperature",
channel: channel,
feature: feature,
payloadMap: parameters);
// Check response (if command has return values)
if (response != null)
{
var successProperty = response.GetType().GetProperty("Success");
if (successProperty != null)
{
var success = ((Boolean)successProperty.GetValue(response, null)).Value;
Console.WriteLine($"Command executed: {success}");
}
}
Parameters: Use the SiLA2 protobuf types from Sila2.Org.Silastandard.Protobuf namespace. Parameter names must match identifiers in the FDL exactly.
Example 4: Executing an Observable Command with Progress Tracking
using Sila2.Org.Silastandard;
using Sila2.Org.Silastandard.Protobuf;
// Prepare command parameters
var parameters = new Dictionary<string, object>
{
{ "TargetTemperature", new Real { Value = 80.0 } },
{ "Duration", new Real { Value = 300.0 } } // 5 minutes
};
// Initiate observable command
var result = dynamicMessageService.ExecuteObservableCommand(
operationName: "StartHeating",
channel: channel,
feature: feature,
payloadMap: parameters);
var commandConfirmation = result.Item1;
var executionInfoStream = result.Item2;
var intermediateStream = result.Item3; // null if no intermediate responses
var responseType = result.Item4;
Console.WriteLine($"Command initiated: {commandConfirmation.CommandExecutionUUID.Value}");
// Monitor execution progress
await foreach (var executionInfo in executionInfoStream)
{
Console.WriteLine($"Status: {executionInfo.CommandStatus}");
Console.WriteLine($"Progress: {executionInfo.ProgressInfo?.Value * 100:F1}%");
if (executionInfo.CommandStatus == ExecutionInfo.Types.CommandStatus.FinishedSuccessfully)
{
Console.WriteLine("Command completed successfully!");
break;
}
else if (executionInfo.CommandStatus == ExecutionInfo.Types.CommandStatus.FinishedWithError)
{
Console.WriteLine($"Command failed: {executionInfo.Message?.Value}");
break;
}
}
// Retrieve final result
var finalResult = dynamicMessageService.GetObservableCommandResult(
cmdId: commandConfirmation.CommandExecutionUUID,
operationName: "StartHeating",
channel: channel,
feature: feature,
responseType: responseType);
// Extract result values
var finalTemp = finalResult.GetType().GetProperty("FinalTemperature");
if (finalTemp != null)
{
var temp = ((Real)finalTemp.GetValue(finalResult, null)).Value;
Console.WriteLine($"Final temperature: {temp}°C");
}
Example 5: Handling Intermediate Responses
// For commands that define IntermediateResponse in FDL
var result = dynamicMessageService.ExecuteObservableCommand(
operationName: "RunExperiment",
channel: channel,
feature: feature,
payloadMap: parameters);
var executionInfoStream = result.Item2;
var intermediateStream = result.Item3;
// Process intermediate responses in parallel with execution info
var intermediateTask = Task.Run(async () =>
{
if (intermediateStream != null)
{
await foreach (var intermediate in intermediateStream)
{
// Extract intermediate data (structure depends on FDL definition)
var currentReading = intermediate.GetType()
.GetProperty("CurrentReading")?.GetValue(intermediate, null);
if (currentReading != null)
{
var reading = ((Real)currentReading).Value;
Console.WriteLine($"Intermediate reading: {reading}");
}
}
}
});
// Monitor execution status
await foreach (var executionInfo in executionInfoStream)
{
if (executionInfo.CommandStatus == ExecutionInfo.Types.CommandStatus.FinishedSuccessfully ||
executionInfo.CommandStatus == ExecutionInfo.Types.CommandStatus.FinishedWithError)
{
break;
}
}
// Wait for intermediate task to complete
await intermediateTask;
// Get final result
var finalResult = dynamicMessageService.GetObservableCommandResult(
result.Item1.CommandExecutionUUID,
"RunExperiment",
channel,
feature,
result.Item4);
Advanced Topics
Handling Complex Data Types
Structure Types
Structures in SiLA2 are nested message types:
// FDL defines a structure like:
// <StructureType>
// <Element>
// <Identifier>X</Identifier>
// <DataType><Basic>Real</Basic></DataType>
// </Element>
// <Element>
// <Identifier>Y</Identifier>
// <DataType><Basic>Real</Basic></DataType>
// </Element>
// </StructureType>
// Create structure instance dynamically
var structureType = Type.GetType("DynamicallyGenerated_CoordinateStructure");
var structureInstance = Activator.CreateInstance(structureType);
// Set nested properties
var xProperty = structureInstance.GetType().GetProperty("X");
xProperty.SetValue(structureInstance, new Real { Value = 10.5 });
var yProperty = structureInstance.GetType().GetProperty("Y");
yProperty.SetValue(structureInstance, new Real { Value = 20.3 });
// Use in command parameters
var parameters = new Dictionary<string, object>
{
{ "Position", structureInstance }
};
List Types
Lists use Google.Protobuf.Collections.RepeatedField<T>:
using Google.Protobuf.Collections;
using Sila2.Org.Silastandard.Protobuf;
// Create a list of strings
var stringList = new RepeatedField<String>();
stringList.Add(new String { Value = "First" });
stringList.Add(new String { Value = "Second" });
stringList.Add(new String { Value = "Third" });
var parameters = new Dictionary<string, object>
{
{ "Names", stringList }
};
var response = dynamicMessageService.ExecuteUnobservableCommand(
"ProcessNames", channel, feature, parameters);
Constrained Types
Constrained types (e.g., Real with min/max) are handled transparently:
// FDL defines constraint: <MinimalInclusive>0</MinimalInclusive>
// The PayloadFactory resolves this to the underlying Real type
var parameters = new Dictionary<string, object>
{
{ "Speed", new Real { Value = 50.0 } } // Constraint validation happens server-side
};
Metadata-Affected Properties
SiLA2 features can define metadata that affects which commands/properties are available. The package supports the FCPAffectedByMetadata_{MetadataIdentifier} pattern:
// Get list of calls affected by specific metadata
var response = dynamicMessageService.GetUnobservableProperty(
propertyName: "FCPAffectedByMetadata_StringMetadata",
channel: channel,
feature: feature);
// Extract affected calls list
var affectedCallsProperty = response.GetType().GetProperty("AffectedCalls");
var affectedCalls = (Google.Protobuf.Collections.RepeatedField<String>)affectedCallsProperty.GetValue(response);
foreach (var call in affectedCalls)
{
Console.WriteLine($"Affected call: {call.Value}");
}
Custom Data Type Resolution
For features with custom defined data types in FDL:
<DataTypeDefinition>
<Identifier>Temperature</Identifier>
<DataType>
<Constrained>
<DataType><Basic>Real</Basic></DataType>
<Constraints>
<MinimalInclusive>-273.15</MinimalInclusive>
<MaximalInclusive>1000.0</MaximalInclusive>
</Constraints>
</Constrained>
</DataType>
</DataTypeDefinition>
The PayloadFactory automatically resolves custom types by traversing the FDL definition tree:
// Usage is transparent - just use the parameter name
var parameters = new Dictionary<string, object>
{
{ "SetPoint", new Real { Value = 25.0 } } // Temperature type resolved to Real
};
Thread Safety Considerations
ModuleBuilder Caching: The DynamicProtobufTypeBuilder uses a shared ModuleBuilder for type generation. While type definition operations are thread-safe, checking for existing types is not atomic.
Recommendation: For multi-threaded scenarios where the same feature might be loaded concurrently, implement a locking strategy around feature initialization:
private static readonly SemaphoreSlim _featureLoadLock = new SemaphoreSlim(1, 1);
private static readonly Dictionary<string, Feature> _featureCache = new();
public async Task<Feature> LoadFeatureAsync(string featurePath)
{
await _featureLoadLock.WaitAsync();
try
{
if (!_featureCache.ContainsKey(featurePath))
{
var feature = FeatureGenerator.ReadFeatureFromFile(featurePath);
_featureCache[featurePath] = feature;
}
return _featureCache[featurePath];
}
finally
{
_featureLoadLock.Release();
}
}
Error Handling Patterns
using Grpc.Core;
try
{
var response = dynamicMessageService.ExecuteUnobservableCommand(
"SetTemperature", channel, feature, parameters);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.InvalidArgument)
{
// SiLA2 validation error (e.g., parameter constraint violation)
Console.WriteLine($"Validation error: {ex.Status.Detail}");
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.FailedPrecondition)
{
// SiLA2 defined execution error
Console.WriteLine($"Execution error: {ex.Status.Detail}");
// Parse SiLA2 error details from metadata
var errorType = ex.Trailers.GetValue("sila2-error-type");
var errorIdentifier = ex.Trailers.GetValue("sila2-error-identifier");
}
catch (RpcException ex)
{
// Other gRPC errors (network, authentication, etc.)
Console.WriteLine($"gRPC error: {ex.StatusCode} - {ex.Status.Detail}");
}
catch (ArgumentException ex)
{
// Invalid property/command name or parameter
Console.WriteLine($"Invalid parameter: {ex.Message}");
}
Comparison with Standard Approach
| Aspect | SiLA2.Communication (Dynamic) | Standard XSLT/protoc |
|---|---|---|
| Setup Time | Instant (load FDL at runtime) | Requires build step |
| Flexibility | Load any feature dynamically | Must recompile for new features |
| Performance | Slower (reflection overhead) | Faster (compiled code) |
| Type Safety | Runtime checks only | Compile-time type checking |
| Code Completion | Limited (dynamic types) | Full IntelliSense support |
| Binary Size | Smaller (no generated code) | Larger (generated assemblies) |
| Use Case | Universal clients, testing | Production feature implementations |
| Debugging | More complex (reflection) | Standard debugging |
| Maintenance | No code generation to maintain | MSBuild targets required |
Performance Benchmark (approximate):
- Standard approach: ~0.5ms per call overhead
- Dynamic approach: ~2-5ms per call overhead (varies with complexity)
For most SiLA2 operations (which involve I/O, device communication, etc.), this overhead is negligible compared to the operation duration.
API Reference Summary
IDynamicMessageService
Main interface for dynamic SiLA2 communication.
public interface IDynamicMessageService
{
// Unobservable property access
object GetUnobservableProperty(
string propertyName,
GrpcChannel channel,
Feature feature,
Grpc.Core.Metadata metadata = null);
// Observable property subscription
IAsyncEnumerable<object> SubcribeObservableProperty(
string propertyName,
GrpcChannel channel,
Feature feature,
Grpc.Core.Metadata metadata = null);
// Unobservable command execution
object ExecuteUnobservableCommand(
string operationName,
GrpcChannel channel,
Feature feature,
IDictionary<string, object> payloadMap = null,
Grpc.Core.Metadata metadata = null);
// Observable command initiation
Tuple<CommandConfirmation, IAsyncEnumerable<ExecutionInfo>,
IAsyncEnumerable<object>, Type> ExecuteObservableCommand(
string operationName,
GrpcChannel channel,
Feature feature,
IDictionary<string, object> payloadMap = null,
Grpc.Core.Metadata metadata = null);
// Observable command result retrieval
object GetObservableCommandResult(
CommandExecutionUUID cmdId,
string operationName,
GrpcChannel channel,
Feature feature,
Type responseType,
Grpc.Core.Metadata metadata = null);
}
IPayloadFactory
Interface for generating dynamic protobuf types from FDL metadata.
public interface IPayloadFactory
{
// Command payload types (request and response)
Tuple<Type, Type> GetCommandPayloadTypes(
Feature feature,
string operation);
// Observable command with intermediate responses
Tuple<Type, Type, Type> GetCommandPayloadTypesWithIntermediateCommandResponseType(
Feature feature,
string operation);
// Property payload types
Tuple<Type, Type> GetPropertyPayloadTypes(
Feature feature,
string property);
}
IDynamicAssemblyBuilder
Provides shared ModuleBuilder for type caching.
public interface IDynamicAssemblyBuilder
{
ModuleBuilder ModuleBuilder { get; }
}
Related Packages
- SiLA2.Core - Core SiLA2 server implementation, domain models, validation
- SiLA2.Client - Standard gRPC client utilities with compile-time stubs
- SiLA2.Client.Dynamic - Higher-level dynamic client built on SiLA2.Communication
- SiLA2.AspNetCore - ASP.NET Core integration for SiLA2 servers
Contributing & Development
This package is part of the sila_csharp project.
Building from Source
git clone --recurse-submodules https://gitlab.com/SiLA2/sila_csharp.git
cd sila_csharp/src
dotnet build SiLA2.Communication/SiLA2.Communication.csproj
Running Tests
dotnet test Tests/SiLA2.Communication.Tests/SiLA2.Communication.Tests.csproj
dotnet test Tests/SiLA2.IntegrationTests.Server.Tests/SiLA2.IntegrationTests.Server.Tests.csproj --filter "FullyQualifiedName~DynamicClient"
Project Structure
SiLA2.Communication/
├── Protobuf/
│ ├── DynamicProtobufTypeBuilder.cs # IL emission-based type generation
│ ├── ProtobufMarshaller.cs # gRPC marshalling for dynamic types
│ └── ByteSerializer.cs # protobuf-net serialization
├── Services/
│ ├── DynamicMessageService.cs # Main gRPC client implementation
│ ├── PayloadFactory.cs # FDL-to-Type mapper
│ ├── DynamicAssemblyBuilder.cs # Shared ModuleBuilder provider
│ └── Interfaces/
└── SiLA2FrameworkEntities.cs # SiLA2 base protobuf types
Links & Resources
- SiLA2 Standard: https://sila-standard.com
- Repository: https://gitlab.com/SiLA2/sila_csharp
- NuGet Package: https://www.nuget.org/packages/SiLA2.Communication
- Documentation Wiki: https://gitlab.com/SiLA2/sila_csharp/-/wikis/home
- Issue Tracker: https://gitlab.com/SiLA2/sila_csharp/-/issues
- SiLA Slack: Join the community
License
This project is licensed under the MIT License.
Maintainer
Christoph Pohl (@Chamundi)
Security
For security vulnerabilities, please refer to the SiLA2 Vulnerability Policy.
Questions or Issues?
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Grpc.AspNetCore (>= 2.76.0)
- protobuf-net (>= 3.2.56)
- protobuf-net.Grpc (>= 1.2.2)
- SiLA2.Core (>= 10.2.2)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on SiLA2.Communication:
| Package | Downloads |
|---|---|
|
SiLA2.Frontend.Razor
Web Frontend Extension for SiLA2.Server Package |
|
|
SiLA2.Client.Dynamic
SiLA2.Client.Dynamic Package |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.2.2 | 40 | 2/12/2026 |
| 10.2.1 | 115 | 1/25/2026 |
| 10.2.0 | 315 | 12/23/2025 |
| 10.1.0 | 524 | 11/29/2025 |
| 10.0.0 | 946 | 11/11/2025 |
| 9.0.4 | 1,226 | 6/25/2025 |
| 9.0.3 | 1,167 | 6/21/2025 |
| 9.0.2 | 1,219 | 1/6/2025 |
| 9.0.1 | 1,211 | 11/17/2024 |
| 9.0.0 | 1,216 | 11/13/2024 |
| 8.1.2 | 1,255 | 10/20/2024 |
| 8.1.1 | 1,314 | 8/31/2024 |
| 8.1.0 | 1,886 | 2/11/2024 |
| 8.0.0 | 1,645 | 11/15/2023 |
| 7.5.4 | 1,292 | 10/27/2023 |
| 7.5.3 | 1,455 | 7/19/2023 |
| 7.5.2 | 1,385 | 7/4/2023 |