Blazor服务器应用程序上的依赖项注入



我正试图用一种通用的方式在我的Blazor应用程序中注入一些服务。我创建了一个接口IService来标识我要注入的服务:

(服务(:

namespace OrbitModule.SpaceRazor.Service
{
public class SpaceRazorService:IService
{
public SpaceRazorService()
{

}
public void DoSomething()
{
}
}
}

(注入服务的Program.cs中的代码(:


IEnumerable<Type> allTypes = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
.Select(x => Assembly.Load(AssemblyName.GetAssemblyName(x)))
.Where(assembly => !assembly.FullName.Contains("Microsoft") && !assembly.FullName.Contains("System") && !assembly.FullName.Contains("NetCore"))
.SelectMany(x => x.GetTypes());
IEnumerable<Type> services = allTypes.Where(x => typeof(IService).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract);
foreach (Type service in services)
{
builder.Services.AddTransient(service); 
}

var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();

为了测试它,我添加了以下内容:

var test = app.Services.GetService(typeof(SpaceRazorService));

当我添加了一个断点时,我看到了服务所需行为的一个实例。。。。

然而,当我创建一个页面时:

@using OrbitModule.SpaceRazor.Service
@page "/SpaceRazor/Page1"
@inject SpaceRazorService spaceRazorService
<h3>List des Spaces Razors</h3>

@code {
void thing()
{
spaceRazorService.DoSomething();
}
}

程序因以下堆栈跟踪而崩溃:

nvalidOperationException: Cannot provide a value for property 'spaceRazorService' on type 'OrbitModule.SpaceRazor.Page.Page1'. There is no registered service of type 'OrbitModule.SpaceRazor.Service.SpaceRazorService'.
Microsoft.AspNetCore.Components.ComponentFactory+<>c__DisplayClass7_0.<CreateInitializer>g__Initialize|1(IServiceProvider serviceProvider, IComponent component)
Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance)
Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType)
Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(ref DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)
Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, int componentId, ArrayRange<RenderTreeFrame> oldTree, ArrayRange<RenderTreeFrame> newTree)
Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, out Exception renderFragmentException)
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender()
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(int componentId, RenderFragment renderFragment)
Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()
Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()
Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.HandleException(Exception exception)
Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleExceptionViaErrorBoundary(Exception error, ComponentState errorSourceOrNull)
Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasks(Task task, ComponentState owningComponentState)
Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView directAndCascadingParameters)
Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)
Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.CreateInitialRenderAsync(Type componentType, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Rendering.HtmlRenderer.RenderComponentAsync(Type componentType, ParameterView initialParameters)
Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c__11<TResult>+<<InvokeAsync>b__11_0>d.MoveNext()
Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.PrerenderComponentAsync(ParameterView parameters, HttpContext httpContext, Type componentType)
Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.PrerenderedServerComponentAsync(HttpContext context, ServerComponentInvocationSequence invocationId, Type type, ParameterView parametersCollection)
Microsoft.AspNetCore.Mvc.ViewFeatures.ComponentRenderer.RenderComponentAsync(ViewContext viewContext, Type componentType, RenderMode renderMode, object parameters)
Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper.ProcessAsync(TagHelperContext context, TagHelperOutput output)
Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner.<RunAsync>g__Awaited|0_0(Task task, TagHelperExecutionContext executionContext, int i, int count)
BlazOrbit.Pages.Pages__Host.ExecuteAsync() in _Host.cshtml
<component type="typeof(App)" render-mode="ServerPrerendered" />
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageCoreAsync(IRazorPage page, ViewContext context)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderPageAsync(IRazorPage page, ViewContext context, bool invokeViewStarts)
Microsoft.AspNetCore.Mvc.Razor.RazorView.RenderAsync(ViewContext context)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor.ExecuteAsync(ViewContext viewContext, string contentType, Nullable<int> statusCode)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResultFilterAsync>g__Awaited|30_0<TFilter, TFilterAsync>(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

但当我直接在@代码中启动服务时,它就起作用了:

@using OrbitModule.SpaceRazor.Service
@page "/SpaceRazor/Page1"
<h3>List des Spaces Razors</h3>

@code {
SpaceRazorService spaceRazorService = new SpaceRazorService();
void thing()
{
spaceRazorService.DoSomething();
}
}

我想知道是否有可能在外部blazor的组件中注入服务。。。。。

可能很重要的细节:

  • 服务在一个外部项目中(如图所示(
  • 接口IService也在另一个项目中

项目的体系结构

试试这个扩展方法:

public static class DependencyInjectionExtensions
{
public static void InstallIServices(
this IServiceCollection services)
{
var assembly = Assembly.GetExecutingAssembly();
RegisterImplementationsOfServiceType(
services, assembly, typeof(IService));
}
private static void RegisterImplementationsOfServiceType(
IServiceCollection services, Assembly assembly, Type type)
{
var implementationsType = assembly.GetTypes()
.Where(x => !x.IsInterface && x.GetInterface(type.Name) != null);
foreach (var implementationType in implementationsType)
{
var servicesType = implementationType.GetInterfaces()
.Where(r => !r.Name.Contains(type.Name));
foreach (var serviceType in servicesType)
{
Console.WriteLine($"{serviceType} , {implementationType}");
services.AddTransient(serviceType, implementationType); //Replace with the type of service they need to be: Transient, Singleton, Scoped
}
}
}
}

用于Program.cs:

public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.InstallIServices();
}

在Startup.cs:中使用

public void ConfigureServices(IServiceCollection services) {
...
services.InstallIServices()
...

最新更新