|
2 | 2 | using Microsoft.AspNetCore.Components.Web;
|
3 | 3 | using BlazorServerSide.Data;
|
4 | 4 |
|
5 |
| -// to get the required properties |
| 5 | +// support for injection of required properties |
6 | 6 | using System.Reflection;
|
7 | 7 | using System.Runtime.CompilerServices;
|
| 8 | +using System.Diagnostics.CodeAnalysis; |
8 | 9 |
|
9 | 10 | using Serilog;
|
10 | 11 | using DryIoc;
|
11 | 12 | using DryIoc.Microsoft.DependencyInjection;
|
12 | 13 |
|
13 | 14 | var builder = WebApplication.CreateBuilder(args);
|
14 | 15 |
|
15 |
| -// todo: @wip take into account constructor with SetsRequiredMembers attribute |
16 |
| -var requiredProperties = PropertiesAndFields.All(withFields: false, |
17 |
| - serviceInfo: (p, _) => p.GetCustomAttribute<RequiredMemberAttribute>() == null ? null |
18 |
| - : PropertyOrFieldServiceInfo.Of(p).WithDetails(ServiceDetails.Of(IfUnresolved.Throw))); |
| 16 | +static PropertyOrFieldServiceInfo? TryInjectRequiredProperties(MemberInfo memberInfo, Request request) |
| 17 | +{ |
| 18 | + if (memberInfo is not PropertyInfo p) |
| 19 | + return null; |
| 20 | + |
| 21 | + // avoid injection of properties if the selected constructor already supposed to set them |
| 22 | + var ctor = request.SelectedConstructor; |
| 23 | + if (ctor != null && ctor.GetCustomAttribute<SetsRequiredMembersAttribute>() != null) |
| 24 | + { |
| 25 | +#if DEBUG |
| 26 | + var logger = request.Container.GetService<ILogger<DryIoc.IContainer>>(); |
| 27 | + logger?.LogDebug("Skipping injection of required property `{PropertyName}` because the selected constructor `{Constructor}` already supposed to set it for service `{ServiceType}`.", p.Name, ctor, request.ServiceType); |
| 28 | +#endif |
| 29 | + return null; |
| 30 | + } |
| 31 | + |
| 32 | + return p.GetCustomAttribute<RequiredMemberAttribute>() == null |
| 33 | + ? null |
| 34 | + : PropertyOrFieldServiceInfo.Of(p).WithDetails(ServiceDetails.Of(IfUnresolved.Throw)); |
| 35 | +} |
19 | 36 |
|
20 |
| -var container = new Container(Rules.MicrosoftDependencyInjectionRules.With(propertiesAndFields: requiredProperties)); |
| 37 | +var tryInjectRequiredProperties = PropertiesAndFields.All(withFields: false, serviceInfo: TryInjectRequiredProperties); |
21 | 38 |
|
| 39 | +var container = new Container(Rules.MicrosoftDependencyInjectionRules.With(propertiesAndFields: tryInjectRequiredProperties)); |
22 | 40 |
|
23 | 41 | // Here it goes the integration with the existing DryIoc container
|
24 | 42 | var diFactory = new DryIocServiceProviderFactory(container, RegistrySharing.Share);
|
25 | 43 | builder.Host.UseServiceProviderFactory(diFactory);
|
26 | 44 |
|
27 |
| - |
28 | 45 | // Add services to the container.
|
29 | 46 | builder.Services.AddRazorPages();
|
30 | 47 | builder.Services.AddServerSideBlazor(options =>
|
|
37 | 54 | .MinimumLevel.Verbose()
|
38 | 55 | .ReadFrom.Configuration(builder.Configuration)
|
39 | 56 | .Enrich.FromLogContext()
|
40 |
| - .WriteTo.File("Errors/Log_.log", rollingInterval: RollingInterval.Day) |
| 57 | + .WriteTo.File("Logs/Log_.log", rollingInterval: RollingInterval.Day) |
41 | 58 | .CreateLogger();
|
42 | 59 | builder.Host.UseSerilog(logger);
|
43 | 60 |
|
44 | 61 |
|
45 |
| -builder.Services.AddSingleton<WeatherForecast>(); // will be injected as required property |
| 62 | +builder.Services.AddTransient<WeatherForecast>(); |
46 | 63 | builder.Services.AddSingleton<WeatherForecastService>();
|
| 64 | +builder.Services.AddSingleton<IRandomProvider, SharedRandomProvider>(); |
47 | 65 |
|
48 | 66 | var app = builder.Build();
|
49 | 67 |
|
|
0 commit comments