Zetian SMTP Server and Zetian.HealthCheck projects now include support for .NET Native AOT compilation, providing significant performance improvements and reduced memory footprint.
- Partial AOT: Core functionality is AOT-compatible
- Trimming Support: Both libraries support trimming
- Minimal Reflection: Limited reflection usage, properly annotated
- JSON with Reflection: JSON serialization uses reflection for flexibility
- Faster Startup: ~50% faster application startup time
- Lower Memory Usage: ~40% reduction in memory footprint
- Smaller Binaries: Reduced deployment size for core functionality
- Better Cold Start: Ideal for containerized and serverless deployments
<PropertyGroup Condition="'$(TargetFramework)' == 'net7.0+'>">
<TrimMode>link</TrimMode>
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
</PropertyGroup><PropertyGroup Condition="'$(TargetFramework)' == 'net7.0+'>">
<TrimMode>partial</TrimMode>
<IsTrimmable>true</IsTrimmable>
<IsAotCompatible>true</IsAotCompatible>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<NoWarn>$(NoWarn);IL2026;IL3050</NoWarn> <!-- Suppress expected warnings -->
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault> <!-- JSON uses reflection -->
</PropertyGroup># Windows (x64)
dotnet publish -c Release -r win-x64 --self-contained
# Linux (x64)
dotnet publish -c Release -r linux-x64 --self-contained
# macOS (ARM64)
dotnet publish -c Release -r osx-arm64 --self-contained# Maximum optimization for production
dotnet publish -c Release -r win-x64 \
--self-contained \
-p:PublishAot=true \
-p:OptimizationPreference=Size \
-p:IlcOptimizationPreference=Size \
-p:IlcGenerateStackTraceData=false \
-p:DebugType=none \
-p:DebugSymbols=falseHealthCheck uses standard JSON serialization with reflection for maximum flexibility:
[RequiresUnreferencedCode("JSON serialization uses reflection")]
[RequiresDynamicCode("JSON serialization may generate code at runtime")]
private async Task WriteJsonResponse(HttpListenerResponse response, object data)
{
string json = JsonSerializer.Serialize(data, new JsonSerializerOptions
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
});
// ...
}Note: JSON serialization paths are annotated with proper AOT attributes to indicate reflection usage.
The HealthCheck project includes a TrimmerRoots.xml file to preserve necessary types:
<?xml version="1.0" encoding="utf-8" ?>
<TrimmerRootDescriptor>
<assemblies>
<assembly fullname="Zetian.HealthCheck">
<type fullname="Zetian.HealthCheck.Models.*" preserve="all" />
<type fullname="Zetian.HealthCheck.Enums.*" preserve="all" />
</assembly>
</assemblies>
</TrimmerRootDescriptor>| Feature | .NET 6.0 | .NET 7.0+ |
|---|---|---|
| Library Usage | ✅ | ✅ |
| Trimming Support | ❌ | ✅ |
| AOT Publishing | ❌ | ✅ |
| Core Functions AOT | ✅ | ✅ |
| JSON Serialization AOT | ❌ | ❌ (uses reflection) |
- Runtime Code Generation: Not supported in AOT mode
- Dynamic Assembly Loading: Not supported in AOT mode
- Health Check Endpoints: May have slightly larger binary size due to preserved JSON types
- JSON Serialization: HealthCheck's JSON endpoints use reflection for flexibility (not fully AOT)
If you need maximum flexibility with JSON:
Option 1: Use Reflection (Current Approach)
- Slightly larger binary size
- Simpler code, works with anonymous types
- JSON serialization methods marked with AOT attributes
Option 2: Use Source Generators (Advanced)
// Define concrete types for all JSON responses
public class HealthCheckResponse { /* properties */ }
// Create source generator context
[JsonSerializable(typeof(HealthCheckResponse))]
public partial class JsonContext : JsonSerializerContext { }
// Use in serialization
JsonSerializer.Serialize(data, JsonContext.Default.HealthCheckResponse);- Custom Code: Avoid reflection in hot paths
- HealthCheck: Accept reflection for JSON flexibility
- Core Library: Use full AOT for maximum performance
- Testing: Test with trimming enabled to catch issues early
- Monitoring: Use the provided health endpoints to monitor AOT apps
Issue: Missing types at runtime Solution: Add types to TrimmerRoots.xml
Issue: Larger binary with health checks Solution: This is expected due to preserved JSON types
Issue: IL2026/IL3050 warnings in HealthCheck Solution: These are expected and suppressed for JSON serialization