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

Create components using dependency injection #5497

Closed
scabana opened this issue Apr 5, 2018 · 6 comments
Closed

Create components using dependency injection #5497

scabana opened this issue Apr 5, 2018 · 6 comments
Assignees
Labels
area-blazor Includes: Blazor, Razor Components investigate

Comments

@scabana
Copy link

scabana commented Apr 5, 2018

From what I see, it would be changing this line: https://github.com/aspnet/Blazor/blob/5be754e75def0c4134e379a6440c6b284828f01e/src/Microsoft.AspNetCore.Blazor/Components/ComponentFactory.cs#L35

Another change would be to allow for interfaces that derives from IComponent in the language service.

The usecases are the following:

  1. Allow for code only components to use constructor injection. The property injection support was native in Asp.Net core while it was in its early stages and was later removed to make the DI simpler and more focussed. This seems to be a step backwards.

  2. Allow this pattern:

//In assembly A
public interface IMyComponent : IComponent { int SomeParameter{get;set;} }

//In assembly B
public class MyComponent: BlazorComponent, IMyComponent { }

//In the blazor app: 

//Setting up dependency injection
class Program
{
    static void Main(string[] args)
    {
        var serviceProvider = new BrowserServiceProvider(configure =>
        {
            //Potentially load implementation dynamically here
            configure.Add(ServiceDescriptor.Transient(typeof(IMyComponent), typeof(MyComponent)));
        });
        new BrowserRenderer(serviceProvider).AddComponent<App>("app");
    }
}

//in cshtml page
<IMyComponent SomeParameter="22" />

How would this be useful: it would become possible to expose components as a contract between multiple assemblies, potentially multiple repositories. This could become the base for a micro-ui architecture where each service could expose their UI components as a contract thus removing the need for a fully pre-built application and allowing dynamically loading components for A/B testing or for testing new features behind feature flags.

@scabana
Copy link
Author

scabana commented Apr 5, 2018

I guess the designer change would need to be here:

https://github.com/aspnet/Blazor/blob/4407de18baac1ad715549b26d292daa1d2fc3658/src/Microsoft.AspNetCore.Blazor.Razor.Extensions/ComponentTagHelperDescriptorProvider.cs#L242-L254

Would need to check those conditions or "is interface".

I'd be glad to make the changes and make a pull request if it would be an acceptable change. Building the vsix with that change to test it should be pretty easy. What do you think?

@scabana
Copy link
Author

scabana commented Apr 6, 2018

This works: https://github.com/scabana/Blazor/commit/4b7f303fe7b423a5a47140a7ac9b636a4d749856
The only thing I'm not 100% sure about is about removing the !isAbstract, I don't know if it opens up the gates too much.
Downside: each component activation now goes through the DI. I could add a cache to persist which one worked and use the right way on second pass.

@scabana
Copy link
Author

scabana commented Apr 7, 2018

I would like to open a pull request with my commit, I don't want to force it before getting buy-in, anyone reviewing issues? Thanks!

@scabana
Copy link
Author

scabana commented Apr 13, 2018

We could go a step further where @injects directives would be only injected by constructor. This would help unit testing the components by making all dependencies very clear. I started looking into this, but I fear it would differ too much from the Asp.Net core's server side Razor.

  1. Use single DI call to init the whole component
  • Easier for unit tests
  • Harder for c# written components with dependencies in the inherited class, this could get messy
  • Easier component initialization in blazor
  • Differs from Asp.Net view initilization
  1. Do not use single DI call for @injects
  • Harder to write unit tests
  • Easier with inheritance
  • Adds "complex" code to build expressions to optimize property injection
  • Mimics Asp,.Net view initialization, easier for future changes and compatibility between the two

@aspnet-hello aspnet-hello transferred this issue from dotnet/blazor Dec 17, 2018
@aspnet-hello aspnet-hello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates area-blazor Includes: Blazor, Razor Components labels Dec 17, 2018
@mkArtakMSFT
Copy link
Member

Thanks for contacting us, @scabana.
@rynowak, can you please look at this? Thanks.

@rynowak
Copy link
Member

rynowak commented Mar 15, 2019

We have no plans to do this for this release.

@rynowak rynowak closed this as completed Mar 15, 2019
@mkArtakMSFT mkArtakMSFT removed area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates labels May 9, 2019
@ghost ghost locked as resolved and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components investigate
Projects
None yet
Development

No branches or pull requests

4 participants