Skip to content

Fix for keyed services. Possible side effects. #424

@Banner-Keith

Description

@Banner-Keith

I noticed an undesirable behavior with using keyed services which I added back in May.

If you inject two keyed services like:

registry.AddKeyedSingleton<ITest, MyTest>(OpenApiTestConstants.TestServiceKey1);
registry.AddKeyedSingleton<ITest, MyOtherTest>(OpenApiTestConstants.TestServiceKey2);

and then you try to access ITest from a constructor like:

public ExampleType(ITest testType)
{
    _testType = testType;
}

you will get the second one that was injected. This behavior seems very likely to result in some accidental bad behavior since the consuming services may get the wrong one without realizing it. The consumers should be specifying which of the two registered ITest services they want using the FromKeyedServices attribute, but if they don't it would be good to alert the developer to that issue.

Another problem is if a non-keyed service is injected in addition to keyed services, that one should always be the one selected when a service is requested without the FromKeyedServices attribute.

example:

registry.AddSingleton<ITest, UnkeyedTest>();
registry.AddKeyedSingleton<ITest, MyTest>(OpenApiTestConstants.TestServiceKey1);
registry.AddKeyedSingleton<ITest, MyOtherTest>(OpenApiTestConstants.TestServiceKey2);

and then you try to access ITest from a constructor I will get MyOtherTest when I should get UnkeyedTest

public ExampleType(ITest testType)
{
    _testType = testType;
}

I have added tests in a branch that fail on this behavior to make it easy to repro and to show the fix. https://github.com/Banner-Keith/lamar/tree/keyed-service-tests

Here's a commit with the following changes to ServiceFamily

  • If there is only one instance matching the service type regardless of if it is keyed or not, set that as the default.
  • If there are any instances matching the service type that are not keyed services, select the last one as default.

This clears this up but may be a breaking change for some consumers that had multiple keyed services injected and have been lucky on it selecting the right one.

Let me know if you agree with my interpretation of what the behavior should be and how we want to handle it. Happy to make additional changes and open a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions