Skip to content

Pass original service key to keyed factories for custom key types - #223

Merged
seesharper merged 1 commit into
masterfrom
fix-custom-service-key-types
Sep 28, 2026
Merged

seesharper merged 1 commit into
masterfrom
fix-custom-service-key-types

Conversation

@seesharper

Copy link
Copy Markdown
Owner

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 in KeyedServiceTypeCache. That cache holds the type of the last key used to resolve the service type.

NServiceBus 10 registers endpoint services with a KeyedServiceKey that wraps the endpoint name. For custom key types like this, the rebuild falls back to Convert.ChangeType("EndpointName", typeof(KeyedServiceKey)), which throws:

System.InvalidOperationException: Unable to convert service key 'EndpointName' to type 'NServiceBus.KeyedServiceKey'.

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's ToString(). The enum, int and string handling is unchanged. Convert.ChangeType is now only used for KeyedService.AnyKey registrations.

Tests

  • Added CompositeServiceKey, a class that behaves like NServiceBus's KeyedServiceKey, plus tests that:
    • pass a custom key through a factory.
    • resolve the same service type alternately with a string key and a custom key.
  • Both tests failed before the fix with the error above.
  • ShouldThrowExceptionWhenUsingInvalidKeyType now uses an AnyKey registration. It used a concrete StringBuilder key, which is now passed through and no longer throws.

Not addressed

KeyedServiceTypeCache is static and 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

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>
@seesharper
seesharper merged commit 3223837 into master Sep 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

LightInject fails to start an NServiceBus 10 endpoint registered with a string endpoint identifier.

1 participant