Aspnetcore: Allow custom component instantiation

Created on 26 Feb 2019  路  10Comments  路  Source: dotnet/aspnetcore

Change the access modifier of ComponentFactory to public to allow instatiation of components.

An even better solution is to add an interface IComponentFactory that is implemented by ComponentFactory and that is registered in the ServiceCollection.

My current use case for this:
I implemented a system to split a blazor/razor-components project into multiple modules that are loaded lazily. The modules define view-extensions that can be rendered whereever needed. The view-extension rendering engines does not know about the concrete type of the component at compile time but needs to instantiate a component (of a type that is known at runtime), configure it with some values and finally render it. Currently I need to copy the source of ComponentFactory to my project to allow this.

If you like, I can implement this and open a PR for it.

area-blazor enhancement

Most helpful comment

@mkArtakMSFT So the workaround is to compile your own version of Blazor? You cannot be serious about that. It is mindboggling that microsoft forces DI upon everyone through the asp.net core framework, yet do not use the same DI container for Component creation with the argument that the framework needs to be in control of component creation. Yet we DO get parameter injection, which makes even less sense.

Allow us to use the container to instantiate components or provide a good argument why the container should not be allowed to be used to instantiate components.

All 10 comments

We've moved this issue to the Backlog milestone. This means that it is not going to happen for the coming release. We will reassess the backlog following the current release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources.

I would also like this feature to be implemented as it would allow me to easier instantiate custom components. The _PR_ as I can see is fairly straightforward so is there a reason why it's not already merged?

Thanks for your PR, @AndreasTruetschel. We still need to think through this. Looking into your workaround, it seems completely reasonable and is what we would recommend. So for now, we're closing your PR till we get a better idea about the direction we would like to take this.

@mkArtakMSFT So the workaround is to compile your own version of Blazor? You cannot be serious about that. It is mindboggling that microsoft forces DI upon everyone through the asp.net core framework, yet do not use the same DI container for Component creation with the argument that the framework needs to be in control of component creation. Yet we DO get parameter injection, which makes even less sense.

Allow us to use the container to instantiate components or provide a good argument why the container should not be allowed to be used to instantiate components.

I agree with @jspuij.

Is there any reason why ComponentFactory.InstantiateComponent method does not use the supplied serviceProvider to create Blazor components, and uses Activator.CreateInstance instead?

The use case we have is where a developer needs to use a custom component, but cannot specify it directly in the .razor files, since the latter are generated, and cannot be updated directly. In this case, they'd be able to register a (__transient__) custom subclass of that component with the DI container and have that subclass instantiated instead of the one specified in the .razor file.

Xomega.Net generates Blazor views from an XML model, with a goal to allow users to change the model and regenerate the views, so any manual changes to the views would be wiped out. At the same time, we want to allow the users to customize the default components that are used in the generated views, and dependency injection would allow them to use a custom subclass.

Also, the component authors would be able to use standard constructor dependency injection, and not just forced to get everything injected into properties with an Inject attribute, for what it's worth.

cc @dotnetjunkie

Thank you! Very much appreciated.

Here's a third use case that seems impossible with the current implementation: injected properties are always resolved from the built-in DI system, never from a third-party 'non-conforming' container.

To me, the solution seems simple, Blazor Components need a similar design as the rest of the system has, i.e. a factory/activator abstraction pair. This means that the internal ComponentFactory should implement a public IComponentFactory factory interface.

@dotnetjunkie When you have constructor injection available I'd completely skip property injection by attribute through the framework. However I do agree with your comment.

To be honest, I'm unsure why the team decided to implement property injection, because to my knowledge non of other parts of the framework apply property injection, the built-in container does not supportnit, and property injection leads to temporal coupling.

Was this page helpful?
0 / 5 - 0 ratings