v1.4.3 "Seiri" - Code Organization & Serialization Cleanup
Release Date: 2025-01-08
Code Name: "Seiri" (整理 - Organization/Cleanup)
Type: Patch Release
🎯 Overview
Version 1.4.3 is a focused cleanup release that eliminates code duplication and resolves serialization issues within the Jiro.Shared library. This release refactors the command result architecture to eliminate redundancy with the main Jiro.Commands project, resulting in cleaner separation of concerns and improved maintainability.
The "Seiri" release embodies the Japanese concept of organization and systematic arrangement, removing unnecessary complexity while maintaining full backward compatibility.
🔧 Breaking Changes
⚠️ Command Result Type Removal
Affected Types (removed from Jiro.Shared):
ICommandResult
interfaceTextResult
classGraphResult
classCommandType
enumTextType
enum
Migration Path:
Applications should use their own ICommandResult
implementations from domain-specific packages (e.g., Jiro.Commands) instead of relying on Jiro.Shared types.
SessionCommandResponse Changes
Before (v1.4.2):
public class SessionCommandResponse
{
public CommandType CommandType { get; set; } // Enum
public ICommandResult? Result { get; set; } // Strongly typed
}
After (v1.4.3):
public class SessionCommandResponse
{
public string CommandType { get; set; } // String for flexibility
public object? Result { get; set; } // Generic object
}
🚀 Key Improvements
Architecture Cleanup
- Eliminated Duplication: Removed duplicate
ICommandResult
types that existed in both Jiro.Shared and Jiro.Commands - Proper Separation: Jiro.Shared now focuses purely on transport/communication contracts
- Domain Independence: Applications can use their own command result implementations
Enhanced Serialization
- Generic Result Handling:
SessionCommandResponse.Result
is nowobject?
for maximum flexibility - JSON Compatibility: Full JSON serialization support with proper type handling
- Framework Agnostic: No dependency on specific result type implementations
gRPC Extension Updates
Updated ClientMessageExtensions
:
// Now creates anonymous objects instead of typed results
Result = new
{
Response = textResult.Response,
TextType = textResult.TextType.ToString().ToLower()
}
📋 Technical Details
Serialization Behavior
The updated SessionCommandResponse
serializes all result types as JSON objects:
String Results:
{
"commandType": "text",
"result": "Simple string result"
}
Complex Results:
{
"commandType": "graph",
"result": {
"message": "Graph data",
"data": "{\"x\":[1,2,3]}",
"units": {"x": "seconds"}
}
}
Consumer Implementation
Applications consuming Jiro.Shared should implement their own result type handling:
// In consuming application
var response = await GetSessionCommandResponse();
if (response.Result is JsonElement element)
{
var myResult = JsonSerializer.Deserialize<MyCustomResult>(element);
// Handle typed result
}
🧪 New Test Coverage
Serialization Tests
Added comprehensive test suite for SessionCommandResponse
serialization:
- String result serialization/deserialization
- Complex object result handling
- Null result handling
- Empty command type scenarios
Test Coverage: 4 new test methods ensuring robust serialization behavior
🔄 Migration Guide
For Library Consumers
- Remove Direct Type Dependencies: Stop importing command result types from Jiro.Shared
- Implement Domain Types: Use your own
ICommandResult
implementations - Update Deserialization: Handle
object?
results with proper type conversion - String Command Types: Update code expecting
CommandType
enum to handle strings
Example Migration
Before:
using Jiro.Shared;
var response = await client.ExecuteCommand();
if (response.Result is TextResult textResult)
{
Console.WriteLine(textResult.Response);
}
After:
using MyApp.Commands; // Your own result types
var response = await client.ExecuteCommand();
if (response.Result is JsonElement element)
{
var textResult = JsonSerializer.Deserialize<MyTextResult>(element);
Console.WriteLine(textResult.Response);
}
🐛 Issues Resolved
- Serialization Conflicts: Eliminated polymorphic serialization issues with abstract types
- Type Duplication: Removed redundant type definitions between projects
- Architecture Coupling: Decoupled transport layer from domain-specific types
- Maintenance Overhead: Reduced code duplication and maintenance burden
📈 Benefits
Development Experience
- Cleaner Architecture: Clear separation between shared infrastructure and domain logic
- Flexible Integration: Applications can define their own result type hierarchies
- Reduced Coupling: No forced dependency on specific command result implementations
Performance & Reliability
- Improved Serialization: Eliminated complex polymorphic serialization scenarios
- Smaller Footprint: Reduced assembly size by removing unnecessary types
- Better Testability: Simplified testing with generic object handling
🔗 Dependencies
No dependency changes in this release. All dependencies remain consistent with v1.4.2:
- Grpc.AspNetCore: 2.71.0
- Google.Protobuf: 3.31.1
- Microsoft.AspNetCore.SignalR: 1.2.0
- Microsoft.AspNetCore.SignalR.Client: 9.0.8
⚡ Compatibility
Backward Compatibility
- Transport Layer: Full compatibility for WebSocket and gRPC communication
- JSON Serialization: Previous JSON structures remain parseable
- Extension Methods:
ClientMessageExtensions
maintain same method signatures
Forward Compatibility
- Extensible Design: Generic
object?
result type supports any future result implementations - Version Agnostic: No version-specific type dependencies
Implementation Note: This release focuses on architectural cleanup and proper separation of concerns. While some types have been removed from Jiro.Shared, the functionality remains available through domain-specific implementations in consuming applications, resulting in a cleaner and more maintainable architecture.