FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

breaking changes: New default AOT compatible dependency resolver, remove most AOT labels. by glennawatson · Pull Request #1461 · reactiveui/splat · GitHub

breaking changes: New default AOT compatible dependency resolver, remove most AOT labels. - #1461

Merged
glennawatson merged 8 commits into
mainfrom
glennawatson/aot-check
Jan 2, 2026
Merged

breaking changes: New default AOT compatible dependency resolver, remove most AOT labels.#1461
glennawatson merged 8 commits into
mainfrom
glennawatson/aot-check

Conversation

glennawatson commented Jan 1, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Summary

This release introduces a new, high-performance dependency resolver designed for AOT (Ahead-of-Time) compilation compatibility, while significantly reducing the trimming attribute burden on your applications.

What Changed

1. New Dependency Resolver Implementation

We've replaced the previous dependency resolver with a new AOT-compatible, generic-first implementation that provides:

  • Better Performance: See benchmark results in the README showing significant improvements in service resolution speed
  • True AOT Compatibility: Works seamlessly with Native AOT compilation without reflection warnings
  • Reduced Memory Allocations: More efficient memory usage during service resolution

2. Simplified Trimming Attributes (Major Developer Experience Improvement)

This is a big win for you as an end user!

Previously, using Splat's dependency injection features required you to annotate your code with various DynamicallyAccessedMembers attributes to satisfy the trimmer. This was burdensome and easy to get wrong.

Now: We've removed the need for almost all trimming attributes!

  • ✅ No more [DynamicallyAccessedMembers] attributes required on your service types
  • ✅ No more trimming warnings when registering and resolving services
  • ⚠️ Only exception: Lazy registrations still require the attribute (due to framework limitations)

Before (you had to do this):

public void RegisterServices(
  [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)]
  Type serviceType)
{
  AppLocator.RegisterLazySingleton(() => Activator.CreateInstance(serviceType));
}

Now (clean and simple):

public void RegisterServices<T>() where T : class, new()
{
  AppLocator.RegisterLazySingleton<T>(() => new T());
}

3. Improved Test Isolation

We've enhanced our test infrastructure with proper scope isolation to prevent state leakage between tests, particularly for:

  • Log4Net logger tests (fixed global repository state issues)
  • Locator tests (proper InternalLocatorScope usage)

This doesn't affect you directly, but ensures higher quality and more reliable releases.

Breaking Changes

Container Swap

The internal dependency resolver implementation has changed. If you're using the public AppLocator API as documented, you should see no breaking changes.

Potential issues only if you:

  • Directly instantiated ModernDependencyResolver (now use InstanceGenericFirstDependencyResolver)
  • Relied on specific internal resolver behaviors

Migration Guide

For most users: No changes needed - the public API remains the same.

If you were using internal APIs:

  • Replace new ModernDependencyResolver() with new InstanceGenericFirstDependencyResolver()
  • Review and remove unnecessary [DynamicallyAccessedMembers] attributes from your code
  • Use the new generic DI methods, they are first class citizens now.

Benefits

  • Faster - Improved performance across the board
  • Cleaner - Less boilerplate trimming attributes
  • AOT-Ready - True Native AOT support without warnings
  • More Reliable - Better test coverage and isolation

Benchmark Results

See the updated README for detailed benchmark comparisons showing performance improvements in:

  • Service registration
  • Service resolution
  • Memory allocation

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

This pull request introduces a major architectural change to Splat's dependency injection system by implementing a new AOT-compatible dependency resolver (InstanceGenericFirstDependencyResolver) to replace ModernDependencyResolver as the default. The PR significantly reduces the need for trimming attributes and improves AOT compatibility.

Key changes:

  • New AOT-compatible dependency resolver with generic-first design pattern
  • Comprehensive test suite for new resolver implementations (InstanceGenericFirst and GlobalGenericFirst)
  • Enhanced test isolation infrastructure with new scope classes
  • Removal of most [DynamicallyAccessedMembers] requirements
  • Updated API surface to include explicit generic overloads in FuncDependencyResolver

Reviewed changes

Copilot reviewed 168 out of 176 changed files in this pull request and generated 50 comments.

Show a summary per file
File Description
src/tests/Splat.Tests/Splat.Tests.csproj Simplified project references, enabled implicit usings, removed logging framework dependencies from core tests
src/tests/Splat.Tests/ServiceLocation/*.cs Added comprehensive test coverage for new resolver implementations including ResolverMixins, NullServiceType, InternalLocator, and base resolver tests
src/tests/Splat.Tests/ServiceLocation/InstanceGenericFirst/*.cs New tests for instance-scoped generic-first resolver components (ContainerCache, ResolverState)
src/tests/Splat.Tests/ServiceLocation/GlobalGenericFirst/*.cs New tests for global generic-first resolver components (ServiceTypeRegistry, Container, ContractContainer, ArrayHelpers, Registration)
src/tests/Splat.Tests/ServiceLocation/ModernDependencyResolverTests.cs Extended tests with disposal, duplication, and edge case coverage
src/tests/Splat.Tests/ServiceLocation/BaseDependencyResolverTests.cs Enhanced base test class with comprehensive generic method coverage and disposal tests
src/tests/Splat.Common.Test/*.cs New test infrastructure including InternalLocatorScope, IMockLogTarget, TextLogger, and improved scope helpers
src/tests/Splat..Tests/.cs Updated integration tests across all framework-specific test projects to use new resolver and generic methods
src/Splat/ServiceLocation/ServiceLocationInitialization.cs Updated to use generic HasRegistration<T>() methods
src/tests/Splat.Tests/API/*.verified.txt Updated API approval snapshots showing new generic overloads in FuncDependencyResolver

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…d bodies

- Updated various test classes to utilize target-typed `new` expressions for cleaner instantiation.
- Simplified method bodies by removing unnecessary braces and return statements in async methods.
- Adjusted assertions to directly use the result of method calls where applicable.
- Ensured consistency across tests in handling null checks and service registrations.

codecov Bot commented Jan 2, 2026
edited
Loading

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.15541% with 617 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.65%. Comparing base (eea5f1b) to head (8f31ad9).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...nericFirst/GlobalGenericFirstDependencyResolver.cs 84.65% 39 Missing and 21 partials ⚠️
.../Splat.SimpleInjector/SimpleInjectorInitializer.cs 30.26% 51 Missing and 2 partials ⚠️
src/Splat.DryIoc/DryIocDependencyResolver.cs 20.96% 49 Missing ⚠️
src/Splat.Logging/WrappingFullLogger.cs 47.05% 40 Missing and 5 partials ⚠️
...ricFirst/InstanceGenericFirstDependencyResolver.cs 90.35% 30 Missing and 13 partials ⚠️
src/Splat.NLog/NLogLogger.cs 50.00% 40 Missing ⚠️
...n/InstanceGenericFirst/ServiceTypeRegistryCache.cs 72.14% 29 Missing and 10 partials ⚠️
...DependencyInjection/MicrosoftDependencyResolver.cs 76.58% 16 Missing and 21 partials ⚠️
...SimpleInjector/SimpleInjectorDependencyResolver.cs 16.66% 32 Missing and 3 partials ⚠️
...t.Core/ServiceLocation/ModernDependencyResolver.cs 87.80% 17 Missing and 13 partials ⚠️
... and 25 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1461      +/-   ##
==========================================
+ Coverage   72.99%   78.65%   +5.66%     
==========================================
  Files         106      116      +10     
  Lines        4447     7014    +2567     
  Branches      607     1109     +502     
==========================================
+ Hits         3246     5517    +2271     
- Misses       1032     1200     +168     
- Partials      169      297     +128     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…ogging features

- Introduced new tests in `FullLoggerExtensionsTests` to validate behavior across all log levels (Debug, Info, Warn, Error, Fatal) for standard loggers, generic loggers, and exception-based loggers.
- Added coverage for `StaticLoggerTests` to verify constructor exception handling.
- Expanded `CoverageColorTests` to include validation tests for known color properties.
- Replaced inline `null!` usage with `Func<string> nullFunc = null!` across all test cases.
- Ensured consistency when testing null argument exceptions for loggers at all levels (Debug, Info, Warn, Error, Fatal).
…DependencyResolver`

- Added null-check handling for contracts in registration methods to enhance robustness.
- Simplified and centralized logic for marking registrations and managing disposables.
- Updated comments and docstrings for clearer documentation and understanding.
- Refactored `GenericFirstDependencyResolver` based classes with improved thread-safety, state handling, and null/unwrapped results processing.
- Updated `HasRegistration` to handle null contracts correctly and align with Splat's expected behavior.
- Enhanced documentation in the README to clarify performance and isolation differences between resolvers.
- Added recommendations for resolver usage and detailed performance characteristics for better user guidance.
glennawatson merged commit 29990fb into main Jan 2, 2026
6 checks passed
glennawatson deleted the glennawatson/aot-check branch January 2, 2026 12:09

Copy link
Copy Markdown

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

github-actions Bot locked as resolved and limited conversation to collaborators Jan 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] ModernDependencyResolver instantiate every registered transient service when disposed.

3 participants


Back | FazBrowse Home | New Git URL