(Alternative request: Create a new ScopedComponent that does this).
When a page descends from OwningComponentBase, all child controls within that component should have their @inject dependencies injected from that new scope.
Dependencies are injected from the main app's scope.
public class Program
{
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddScoped<SomeService>();
builder.RootComponents.Add<App>("app");
await builder.Build().RunAsync();
}
}
public class SomeService
{
private static volatile int NextId;
public int Id { get; set; }
public SomeService()
{
Id = Interlocked.Increment(ref NextId);
}
}
//========================Index.razor
@page "/"
@inherits OwningComponentBase<IServiceProvider>
<br />
<CascadingValue Value=@Service>
<EmbeddedComponent/>
</CascadingValue>
//========================EmbeddedComponent.razor
@page "/counter"
@inject SomeService InjectedService
<p>
Injected value = @InjectedService.Id
</p>
<p>
Resolved value = @ResolvedService.Id
</p>
@code
{
[CascadingParameter]
public IServiceProvider ServiceProvider { get; set; }
private SomeService ResolvedService;
protected override void OnInitialized()
{
base.OnInitialized();
ResolvedService = (SomeService)ServiceProvider.GetService(typeof(SomeService));
}
}
Desired output:
Injected value = 1
Resolved value = 1
Actual output:
Injected value = 1
Resolved value = 2
@mrpmorris thanks for contacting us.
That is not a feature that we have and it is not something we are likely to add as it would result in a very convoluted model where it would be really hard to reason about a component dependency as its scope would be based on what its parent is and might vary if a component is the child of different component types, which I don't think is a trait we want to have.
If you want to achieve this you can do so by creating and resolving the dependency on the parent component and exposing it as cascading parameter for the children, but that is also not something we recommend or alternatively implementing this yourself by:
As i said, this is not something we plan to implement and we discourage you from going this way.
@javiercn This would make it the same as the way ASP MVC requests work for the pages that the developer wants to descend from OwningComponentBase. A per-page scope.
Currently, the lifetimes are confusing
Perhaps if we had a new ScopedComponent we could at least make Scoped behave the same way as one would expect coming from ASP.NET development.
Having to cascade services, or a service provider is too much work. Also, the owning page has to be aware of the dependencies of all of its inner contents no matter how deeply nested they are. It would be better to be able explicitly just state that the Scoped components in this page exist for the lifetime of this page only.
As for your recommendation to not proceed using any of the suggested approaches. It begs the question, why does OwningComponentBase<T> exist at all in that case? :)
@mrpmorris Frankly, OwningComponentBase
I never use it. I'll create a specific factory for the specific type(s) I need and pass the scoped service as a parameter to other controls if they need it. The whole DI in blazor is messed up (again, like any DI implementation MS does), and I mostly try to work around it.
Source is here: https://github.com/dotnet/aspnetcore/blob/3148acfb105a16aa6c535d00eb0e50ec03992f3f/src/Components/Components/src/OwningComponentBase.cs
I too would like to sidestep this issue by using a better DI container.
Most helpful comment
@javiercn This would make it the same as the way ASP MVC requests work for the pages that the developer wants to descend from OwningComponentBase. A per-page scope.
Currently, the lifetimes are confusing
Perhaps if we had a new ScopedComponent we could at least make Scoped behave the same way as one would expect coming from ASP.NET development.
Having to cascade services, or a service provider is too much work. Also, the owning page has to be aware of the dependencies of all of its inner contents no matter how deeply nested they are. It would be better to be able explicitly just state that the Scoped components in this page exist for the lifetime of this page only.
As for your recommendation to not proceed using any of the suggested approaches. It begs the question, why does
OwningComponentBase<T>exist at all in that case? :)