diff --git a/Directory.Build.props b/Directory.Build.props
index 2695885..c28e3a6 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -66,8 +66,7 @@
-
- $(NoWarn);CA1014;CA1031;CA1052;CA1515;CA1707;CA1724;CA1812;CA1848;CA1852;CA2007;RCS1102;IL2026;IL2067;IL2070;IL2075;IL3050;IL2104;IL3053
+$(NoWarn);CA1014;CA1031;CA1052;CA1515;CA1707;CA1724;CA1812;CA1848;CA1852;CA2007;RCS1102
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0731f86..fb0f1b7 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -4,7 +4,9 @@
true
+
+
diff --git a/kanban/done/002-fix-aot-trim-warnings.md b/kanban/done/002-fix-aot-trim-warnings.md
new file mode 100644
index 0000000..1b2f28a
--- /dev/null
+++ b/kanban/done/002-fix-aot-trim-warnings.md
@@ -0,0 +1,66 @@
+# Fix AOT and Trim Warnings
+
+## Summary
+
+Package produces IL2104/IL3053 trim and AOT analysis warnings when used in applications published with `PublishAot=true`. The package needs to be made fully AOT-compatible.
+
+**GitHub Issue:** #7
+
+## Todo List
+
+- [x] Identify reflection usage causing trim warnings
+- [x] Add `[DynamicallyAccessedMembers]` attributes where needed
+- [x] Consider source generators for reflection-based binding
+- [x] Add `true` to project
+- [x] Add `true` to project
+- [x] Test with AOT publish to verify zero warnings
+- [ ] Update package version
+
+## Notes
+
+**Current warnings:**
+```
+TimeWarp.OptionsValidation.dll : warning IL2104: Assembly 'TimeWarp.OptionsValidation' produced trim warnings.
+TimeWarp.OptionsValidation.dll : warning IL3053: Assembly 'TimeWarp.OptionsValidation' produced AOT analysis warnings.
+```
+
+**Reproduction steps:**
+1. Create a .NET 10 application using `TimeWarp.OptionsValidation`
+2. Use `AddFluentValidatedOptions(config)`
+3. Publish with AOT: `dotnet publish -p:PublishAot=true`
+
+**Package Version:** 1.0.0-beta.3
+
+**Related:** TimeWarp.Nuru task 018-make-configuration-validation-sample-aot-compatible
+
+## Results
+
+### Changes Made:
+
+**1. `service-collection-extensions.cs`**
+- Added `using System.Diagnostics.CodeAnalysis;`
+- Added `[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]` to `TOptions` on the configuration binding overload (required by `Bind()`)
+- Added `[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]` to `TValidator` on both overloads
+
+**2. `options-builder-extensions.cs`**
+- Added `using System.Diagnostics.CodeAnalysis;`
+- Added `[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]` to `TValidator` (required by `TryAddSingleton()`)
+
+**3. `timewarp-options-validation.csproj`**
+- Added `true`
+- Added `true`
+
+**4. New AOT test project** (`tests/aot-test/`)
+- Created test project that publishes with AOT to verify no trim/AOT warnings
+
+### Test Results:
+
+| Test | Result |
+|------|--------|
+| `dotnet build -warnaserror` | ✅ 0 warnings, 0 errors |
+| `dotnet test` | ✅ Passed: 4, Skipped: 1 |
+| `dotnet publish -c Release` (AOT) | ✅ 0 IL2104/IL3053 warnings |
+| Run AOT binary | ✅ Output: "Name: Test, Value: 42" |
+
+### Decision:
+Source generators were not needed - the `[DynamicallyAccessedMembers]` attributes were sufficient to eliminate all warnings while maintaining full AOT compatibility.
diff --git a/source/Directory.Build.props b/source/Directory.Build.props
index eb92710..9eeb8d1 100644
--- a/source/Directory.Build.props
+++ b/source/Directory.Build.props
@@ -4,7 +4,7 @@
- 1.0.0-beta.3
+ 1.0.0-beta.4
Steven T. Cramer
TimeWarp Enterprises
TimeWarp.OptionsValidation
diff --git a/source/timewarp-options-validation/extensions/options-builder-extensions.cs b/source/timewarp-options-validation/extensions/options-builder-extensions.cs
index 1fa6f02..9a03653 100644
--- a/source/timewarp-options-validation/extensions/options-builder-extensions.cs
+++ b/source/timewarp-options-validation/extensions/options-builder-extensions.cs
@@ -1,5 +1,6 @@
namespace Microsoft.Extensions.Options;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using FluentValidation;
@@ -26,7 +27,7 @@ public static class OptionsBuilderExtensions
/// .ValidateOnStart();
///
///
- public static OptionsBuilder ValidateFluentValidation(
+ public static OptionsBuilder ValidateFluentValidation(
this OptionsBuilder optionsBuilder)
where TOptions : class
where TValidator : AbstractValidator
diff --git a/source/timewarp-options-validation/extensions/service-collection-extensions.cs b/source/timewarp-options-validation/extensions/service-collection-extensions.cs
index 54321e0..e6620b5 100644
--- a/source/timewarp-options-validation/extensions/service-collection-extensions.cs
+++ b/source/timewarp-options-validation/extensions/service-collection-extensions.cs
@@ -1,5 +1,6 @@
-namespace Microsoft.Extensions.DependencyInjection;
+namespace Microsoft.Extensions.DependencyInjection;
+using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Options;
public static class ServiceCollectionExtensions
@@ -34,7 +35,9 @@ public static class ServiceCollectionExtensions
/// .ValidateOnStart();
///
///
- public static OptionsBuilder AddFluentValidatedOptions(
+ [RequiresUnreferencedCode("TOptions's dependent types may have their members trimmed. Ensure all required members are preserved.")]
+ [RequiresDynamicCode("Binding strongly typed objects to configuration values may require generating dynamic code at runtime.")]
+ public static OptionsBuilder AddFluentValidatedOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TOptions, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] TValidator>(
this IServiceCollection services,
IConfiguration configuration)
where TOptions : class
@@ -71,7 +74,7 @@ public static OptionsBuilder AddFluentValidatedOptions
///
- public static OptionsBuilder AddFluentValidatedOptions(
+ public static OptionsBuilder AddFluentValidatedOptions(
this IServiceCollection services,
Action configureOptions)
where TOptions : class
diff --git a/source/timewarp-options-validation/timewarp-options-validation.csproj b/source/timewarp-options-validation/timewarp-options-validation.csproj
index e1cddd4..965886d 100644
--- a/source/timewarp-options-validation/timewarp-options-validation.csproj
+++ b/source/timewarp-options-validation/timewarp-options-validation.csproj
@@ -3,6 +3,8 @@
TimeWarp.OptionsValidation
TimeWarp.OptionsValidation
+ true
+ true
diff --git a/tests/aot-test/aot-test.csproj b/tests/aot-test/aot-test.csproj
new file mode 100644
index 0000000..af2ac9c
--- /dev/null
+++ b/tests/aot-test/aot-test.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net10.0
+ enable
+ enable
+ true
+ true
+
+
+
+
+
+
+
+
+
diff --git a/tests/aot-test/program.cs b/tests/aot-test/program.cs
new file mode 100644
index 0000000..25e88c5
--- /dev/null
+++ b/tests/aot-test/program.cs
@@ -0,0 +1,48 @@
+using FluentValidation;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using TimeWarp.OptionsValidation;
+
+namespace AotTest;
+
+internal static class Program
+{
+ public static void Main()
+ {
+ // Create configuration
+ IConfigurationRoot configuration = new ConfigurationBuilder()
+ .AddInMemoryCollection(new Dictionary
+ {
+ ["TestOptions:Name"] = "Test",
+ ["TestOptions:Value"] = "42"
+ })
+ .Build();
+
+ // Setup DI with options validation
+ ServiceCollection services = new();
+ services.AddFluentValidatedOptions(configuration)
+ .ValidateOnStart();
+
+ ServiceProvider serviceProvider = services.BuildServiceProvider();
+ IOptions options = serviceProvider.GetRequiredService>();
+
+ Console.WriteLine($"Name: {options.Value.Name}, Value: {options.Value.Value}");
+ }
+}
+
+[ConfigurationKey("TestOptions")]
+internal sealed class TestOptions
+{
+ public string Name { get; set; } = string.Empty;
+ public int Value { get; set; }
+}
+
+internal sealed class TestOptionsValidator : AbstractValidator
+{
+ public TestOptionsValidator()
+ {
+ RuleFor(x => x.Name).NotEmpty();
+ RuleFor(x => x.Value).GreaterThan(0);
+ }
+}