Skip to content

Instantly share code, notes, and snippets.

@gitcob
Created November 17, 2020 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gitcob/9a4092d583947d622efb4a70a262ea48 to your computer and use it in GitHub Desktop.
Save gitcob/9a4092d583947d622efb4a70a262ea48 to your computer and use it in GitHub Desktop.
Blazor Server App with Simple Injector issue
using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Components;
using SimpleInjector.Advanced;
namespace BlazorApp1
{
public sealed class InjectPropertySelectionBehavior : IPropertySelectionBehavior
{
public bool SelectProperty(Type implementationType, PropertyInfo prop) =>
prop.GetCustomAttributes(typeof(InjectAttribute)).Any();
}
}
fail: Microsoft.AspNetCore.Components.Server.Circuits.CircuitHost[111]
Unhandled exception in circuit 'KC8Jj8keAWjOJN4IdmgP_cjWj3iSP7k1eoY5T10DzcU'.
System.InvalidOperationException: Cannot provide a value for property 'ForecastService' on type 'BlazorApp1.Pages.FetchData'. There is no registered service of type 'BlazorApp1.Data.WeatherForecastService'.
at Microsoft.AspNetCore.Components.ComponentFactory.<>c__DisplayClass6_0.<CreateInitializer>g__Initialize|2(IServiceProvider serviceProvider, IComponent component)
at Microsoft.AspNetCore.Components.ComponentFactory.PerformPropertyInjection(IServiceProvider serviceProvider, IComponent instance)
at Microsoft.AspNetCore.Components.ComponentFactory.InstantiateComponent(IServiceProvider serviceProvider, Type componentType)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.InstantiateChildComponentOnFrame(RenderTreeFrame& frame, Int32 parentComponentId)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& diffContext, Int32 frameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& diffContext, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForFramesWithSameSequence(DiffContext& diffContext, Int32 oldFrameIndex, Int32 newFrameIndex)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& diffContext, Int32 oldStartIndex, Int32 oldEndIndexExcl, Int32 newStartIndex, Int32 newEndIndexExcl)
at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, Int32 componentId, ArrayRange`1 oldTree, ArrayRange`1 newTree)
at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry) at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Components;
using SimpleInjector;
namespace BlazorApp1
{
public sealed class SimpleInjectorComponentActivator : IComponentActivator
{
private readonly Dictionary<Type, InstanceProducer<IComponent>> _applicationProducers;
public SimpleInjectorComponentActivator(Container container, Assembly[] assemblies)
{
_applicationProducers = (
from type in container.GetTypesToRegister<IComponent>(assemblies)
let producer = Lifestyle.Transient.CreateProducer<IComponent>(type, container)
select (type, producer))
.ToDictionary(v => v.type, v => v.producer);
}
public IComponent CreateInstance(Type type) =>
_applicationProducers.TryGetValue(type, out var producer)
? producer.GetInstance()
: DefaultCreateInstance(type);
private static IComponent DefaultCreateInstance(Type componentType)
{
var instance = Activator.CreateInstance(componentType);
if (!(instance is IComponent component))
{
throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
}
return component;
}
}
}
using BlazorApp1.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SimpleInjector;
using SimpleInjector.Advanced;
using SimpleInjector.Lifestyles;
namespace BlazorApp1
{
public sealed class InjectPropertySelectionBehavior : IPropertySelectionBehavior
{
public bool SelectProperty(Type implementationType, PropertyInfo prop) =>
prop.GetCustomAttributes(typeof(InjectAttribute)).Any();
}
public sealed class SimpleInjectorComponentActivator : IComponentActivator
{
private readonly Dictionary<Type, InstanceProducer<IComponent>> _applicationProducers;
public SimpleInjectorComponentActivator(Container container, Assembly[] assemblies)
{
_applicationProducers = (
from type in container.GetTypesToRegister<IComponent>(assemblies)
let producer = Lifestyle.Transient.CreateProducer<IComponent>(type, container)
select (type, producer))
.ToDictionary(v => v.type, v => v.producer);
}
public IComponent CreateInstance(Type type) =>
_applicationProducers.TryGetValue(type, out var producer)
? producer.GetInstance()
: DefaultCreateInstance(type);
private static IComponent DefaultCreateInstance(Type componentType)
{
var instance = Activator.CreateInstance(componentType);
if (!(instance is IComponent component))
{
throw new ArgumentException($"The type {componentType.FullName} does not implement {nameof(IComponent)}.", nameof(componentType));
}
return component;
}
}
public class Startup
{
private readonly Container _container;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
_container = new Container
{
Options =
{
DefaultScopedLifestyle = new AsyncScopedLifestyle(),
ResolveUnregisteredConcreteTypes = true,
UseStrictLifestyleMismatchBehavior = true,
PropertySelectionBehavior = new InjectPropertySelectionBehavior()
}
};
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
// services.AddSingleton<WeatherForecastService>(); <- Template uses the built-in DI to register the service
// Sets up the basic configuration that for integrating Simple Injector with
// ASP.NET Core by setting the DefaultScopedLifestyle, and setting up auto
// cross wiring.
services.AddSimpleInjector(_container, options =>
{
// AddAspNetCore() wraps web requests in a Simple Injector scope and
// allows request-scoped framework services to be resolved.
options.AddAspNetCore(ServiceScopeReuseBehavior.OnePerRequest)
// Ensure activation of a specific framework type to be created by
// Simple Injector instead of the built-in configuration system.
// All calls are optional. You can enable what you need. For instance,
// ViewComponents, PageModels, and TagHelpers are not needed when you
// build a Web API.
.AddControllerActivation()
.AddViewComponentActivation()
.AddPageModelActivation()
.AddTagHelperActivation();
});
var autoRegistrationAssemblies = new[] { typeof(Startup).Assembly };
services.AddSingleton<IComponentActivator>(
new SimpleInjectorComponentActivator(_container, autoRegistrationAssemblies));
_container.Register<WeatherForecastService>(); // <- Registration moved here
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
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.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment