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

Constructor injection for Blazor components #18088

Closed
SQL-MisterMagoo opened this issue Jan 2, 2020 · 27 comments · Fixed by #53915
Closed

Constructor injection for Blazor components #18088

SQL-MisterMagoo opened this issue Jan 2, 2020 · 27 comments · Fixed by #53915
Assignees
Labels
affected-medium This issue impacts approximately half of our customers area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-component-model Any feature that affects the component model for Blazor (Parameters, Rendering, Lifecycle, etc) Pillar: Complete Blazor Web Priority:1 Work that is critical for the release, but we could probably ship without severity-minor This label is used by an internal tool
Milestone

Comments

@SQL-MisterMagoo
Copy link
Contributor

Is your feature request related to a problem? Please describe.

Constructor injection in Components was ruled out previously as "we don't plan to do this" but now that we have partials is there any change in this attitude?
see #15779 , #5497

Describe the solution you'd like

If Blazor could be modified to optionally use DI to source components, then constructor injection would be possible,

If you would be open to at least reviewing a PR, I'm sure the community would do the groundwork to make it happen.

@pranavkm pranavkm added area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one labels Jan 2, 2020
@pranavkm pranavkm added this to the Backlog milestone Jan 2, 2020
@pranavkm
Copy link
Contributor

pranavkm commented Jan 2, 2020

Thanks for your issue report. We'll consider whether to address this during our next milestone planning.

@SQL-MisterMagoo
Copy link
Contributor Author

Thanks for that

@nvmkpk
Copy link

nvmkpk commented Apr 9, 2020

This is a must have. Property based injection prevents us from consuming them within the constructor there by preventing us from making some (other) fields read only.

@YairHalberstadt
Copy link

Comment from a duplicate issue I opened:

Currently blazor only allows injecting services into components using property injection via the [Inject] attribute.

However this has a number of disadvantages over constructor injection

  1. NRTs
    The compiler warns if you declare you service as non-nullable, and nullable reference types are enabled. You have to manually suppress the warning.
  2. Immutablility
    You cannot declare the services readonly, since they need to be set by the injector.
  3. Manual construction
    If you create the component manually (perhaps for unit testing), there is nothing to guarentee you will set the services. Even worse - you often can't since the properties are usually private. You have to declare two constructors - one parameterless, and one which sets all the services. This is needless code duplication, and means that test and app code go through different paths, which is undesirable.
  4. Validation
    The constructor is a place where you can validate all your services, and do transformations on them. Perhaps, you don't want to store your services, but just call one service with another service, and store the result. Constructors are a good place to do that, with property injection this is tricky.

Proposal

If there is a single constructor, use it for dependency injection. It is an error if any of the parameters cannot be resolved. It is an error if there are multiple constructors, none of which are parameterless, unless one of them is marked with [Inject]. After the construction, property injection takes place.

@nvmkpk
Copy link

nvmkpk commented May 27, 2020

InjectAttribute cannot be set on non-properties. There is already ActivatorUtilitiesConstructorAttribute available for decorating a constructor to be used by DI.

@ClassyCircuit
Copy link

ClassyCircuit commented Jul 23, 2020

Any updates on this? @pranavkm

@mkArtakMSFT
Copy link
Member

Moving to backlog given this now be achieved using IComponentActivator.

@ghost
Copy link

ghost commented Jul 23, 2020

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@ClassyCircuit
Copy link

@mkArtakMSFT how can it be achieved using IComponentActivator? Could you please give an example?

@steveharter
Copy link
Member

@danroth27 @mkArtakMSFT

We think this is currently blocked on dotnet/runtime#66153

That is now unblocked. There is still perf research\work to do here on the DI side, but the size regression is no longer blocked. There is now a reflection path that doesn't use LINQ.

@mkArtakMSFT mkArtakMSFT modified the milestones: .NET 8 Planning, Backlog Jun 29, 2023
@ghost
Copy link

ghost commented Jun 29, 2023

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@ghost
Copy link

ghost commented Dec 19, 2023

Thanks for contacting us.

We're moving this issue to the .NET 9 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s).
If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues.
To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@mkArtakMSFT mkArtakMSFT removed the Priority:2 Work that is important, but not critical for the release label Dec 19, 2023
@mkArtakMSFT mkArtakMSFT added the Priority:1 Work that is critical for the release, but we could probably ship without label Jan 17, 2024
@danroth27 danroth27 changed the title Can we talk about constructor injection now that partial classes are here? Constructor injection for Blazor components Jan 30, 2024
@Dargazo
Copy link

Dargazo commented Jul 2, 2024

Comment from a duplicate issue I opened:

Currently blazor only allows injecting services into components using property injection via the [Inject] attribute.

However this has a number of disadvantages over constructor injection

1. NRTs
   The compiler warns if you declare you service as non-nullable, and nullable reference types are enabled. You have to manually suppress the warning.

2. Immutablility
   You cannot declare the services readonly, since they need to be set by the injector.

3. Manual construction
   If you create the component manually (perhaps for unit testing), there is nothing to guarentee you will set the services. Even worse - you often can't since the properties are usually private. You have to declare two constructors - one parameterless, and one which sets all the services. This is needless code duplication, and means that test and app code go through different paths, which is undesirable.

4. Validation
   The constructor is a place where you can validate all your services, and do transformations on them. Perhaps, you don't want to store your services, but just call one service with another service, and store the result. Constructors are a good place to do that, with property injection this is tricky.

...

Looks like this is going to make it into .NET 9, which is great!

In the meantime, items 1, and 3 can be addressed by marking the service properties 'public required' and e.g. use an 'init' setter. Although not ideal, it might be preferable to suppressing the nullability warnings

@andrewrondeau-optirtc
Copy link

andrewrondeau-optirtc commented Jul 5, 2024

In the meantime, items 1, and 3 can be addressed by marking the service properties 'public required' and e.g. use an 'init' setter. Although not ideal, it might be preferable to suppressing the nullability warnings

Yes, that is the best workaround. I was setting the properties to "null!" (notice the exclamation mark) until I discovered the "required" keyword.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affected-medium This issue impacts approximately half of our customers area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one feature-blazor-component-model Any feature that affects the component model for Blazor (Parameters, Rendering, Lifecycle, etc) Pillar: Complete Blazor Web Priority:1 Work that is critical for the release, but we could probably ship without severity-minor This label is used by an internal tool
Projects
None yet
Development

Successfully merging a pull request may close this issue.