Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improving GenericParameter and OptionalGenericParameter injection parameters #294

Open
ENikS opened this issue Dec 4, 2020 · 0 comments
Assignees
Labels
Breaking change ❕ This change breaks public API Bug 🐛
Milestone

Comments

@ENikS
Copy link
Contributor

ENikS commented Dec 4, 2020

Generic Parameter injection members

Unity implements several classes representing generic parameters:

  • GenericParameter
  • OptionalGenericParameter

These are useful when registering generic types. For example, consider the following two types:

public class TestType<TDependency>
{
    public TestType([Dependency] TDependency value) { }
    ...
}


public class NamedTestType<TDependency>
{
    public NamedTestType([Dependency("name")] TDependency value) { }
    ...
}

Both of these classes have constructors that import a dependency, but one is anonymous and the other one is named.

To register these types you would do something like this:

Container.RegisterType(typeof(TestType), new InjectionConstructor( new GenericParameter("TDependency")));

Container.RegisterType(typeof(NamedTestType), new InjectionConstructor(new OptionalGenericParameter("TDependency")));

These registrations would instruct Unity to select a constructor taking one parameter and resolve associated value. You register rest of your types:

Container.RegisterInstance("registered")
         .RegisterInstance("name", "named");

and now try to resolve: Container.Resolve<TestType<string>>()

Current Behavior

The container will return a type initialized with the string: "registered". Accordingly, when you resolve Container.Resolve<NamedTestType<string>>() you would expect an instance of NamedTestType type initialized with the string "named", but instead, you will still be getting "registered".

The constructor GenericParameter("TDependency") overrides whatever name is associated with dependency with null. To get correct import you would have to register it like this:

Container.RegisterType(...,(new OptionalGenericParameter("TDependency", "name")));

Problem

This implementation severely limits usability of names in generics and places restrictions on what could be done. Developers need to know at design time all the required names and must manually provide these while coding.

Solution

The proposed solution is to allow default constructor to match any name provided by the type of associated attributes.

Impact

This modification in behavior would create a breaking change and would require changes in code. In cases where dependencies are named, instead of default, Unity will resolve named registrations.
To work around these issues registrations like these GenericParameter("TDependency") should be replaced with GenericParameter("TDependency", null). For Optional dependencies it should be: OptionalGenericParameter("TDependency", null)

@ENikS ENikS self-assigned this Dec 4, 2020
@ENikS ENikS added Breaking change ❕ This change breaks public API Enhancement 🔨 Improvement of existing features labels Dec 4, 2020
@ENikS ENikS added this to the 6.0.0 milestone Dec 4, 2020
@github-actions github-actions bot added the release Release branch label Dec 5, 2020
@ENikS ENikS added Bug 🐛 and removed Enhancement 🔨 Improvement of existing features labels Dec 12, 2020
@ENikS ENikS removed the release Release branch label Mar 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Breaking change ❕ This change breaks public API Bug 🐛
Projects
None yet
Development

No branches or pull requests

1 participant