Pass original service key to keyed factories for custom key types - #223
Merged
Merged
Conversation
When a keyed factory is invoked, the service key is reconstructed from LightInject's string service name. For custom key types (e.g. NServiceBus' KeyedServiceKey) this fell through to Convert.ChangeType, which fails. If the cached key type matches the type of the registered key, pass the registered key instance to the factory instead. Conversion is now only needed for KeyedService.AnyKey registrations. Fixes seesharper/LightInject#618 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes seesharper/LightInject#618
Problem
LightInject stores keyed services under
ServiceKey.ToString(). When a keyed factory runs, the key object is rebuilt from that string, using the type recorded inKeyedServiceTypeCache. That cache holds the type of the last key used to resolve the service type.NServiceBus 10 registers endpoint services with a
KeyedServiceKeythat wraps the endpoint name. For custom key types like this, the rebuild falls back toConvert.ChangeType("EndpointName", typeof(KeyedServiceKey)), which throws:Fix
In
CreateTypedKeyedFactoryDelegate, if the cached key type matches the type of the registered key, the factory now gets the registered key instance (serviceDescriptor.ServiceKey). Rebuilding from the string isn't needed there, because LightInject found the registration by matching that key'sToString(). The enum, int and string handling is unchanged.Convert.ChangeTypeis now only used forKeyedService.AnyKeyregistrations.Tests
CompositeServiceKey, a class that behaves like NServiceBus'sKeyedServiceKey, plus tests that:ShouldThrowExceptionWhenUsingInvalidKeyTypenow uses anAnyKeyregistration. It used a concreteStringBuilderkey, which is now passed through and no longer throws.Not addressed
KeyedServiceTypeCacheisstaticand indexed only by service type, so all containers share it and the last key type used wins. This PR makes that much less likely to cause problems, but a per-container cache would be a separate improvement.🤖 Generated with Claude Code