Skip to content

Commit 81ba56e

Browse files
committed
feat(NamedOptions): Implement CodeSampleOptions by Name
BUG: only the NavigationSamples CodeSampleService does get resolved but while they are called as required, there is no excption thrown?
1 parent 22e3c48 commit 81ba56e

17 files changed

+172
-174
lines changed

.editorconfig

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,69 +8,39 @@ root = true
88
# Common Settings
99
##########################################
1010

11+
1112
[*]
1213
indent_style = space
1314
end_of_line = crlf
1415
trim_trailing_whitespace = true
15-
insert_final_newline = true
16+
insert_final_newline = false
1617
charset = utf-8
1718

18-
##########################################
19-
# File Extension Settings
20-
##########################################
21-
22-
[*.{yml,yaml}]
23-
indent_size = 2
24-
25-
[.vsconfig]
19+
[*.{md,markdown,json,txt,log,yml,yaml,jsonc}]
2620
indent_size = 2
27-
end_of_line = lf
21+
indent_style = space
2822

29-
[*.sln]
30-
indent_style = tab
31-
indent_size = 2
23+
[*.{md,markdown}]
24+
insert_final_newline = true
25+
trim_trailing_whitespace = true
3226

33-
[*.{csproj,proj,projitems,shproj}]
34-
indent_size = 4
27+
##########################################
28+
# File Extension Settings
29+
##########################################
3530

36-
[*.{json,slnf}]
31+
[*.{xaml,xml,slnf,sln,csproj,proj,projitems,shproj,props,targets,appxmanifest,html,cshtml,webmanifest,manifest,css,vsconfig,sh}]
3732
indent_size = 2
38-
end_of_line = lf
39-
40-
[*.{props,targets}]
41-
indent_size = 4
42-
43-
[*.xaml]
44-
indent_size = 4
45-
charset = utf-8-bom
46-
47-
[*.xml]
48-
indent_size = 4
49-
end_of_line = lf
33+
indent_style = space
5034

5135
[*.plist]
5236
indent_size = 4
5337
indent_style = tab
5438
end_of_line = lf
5539

56-
[*.manifest]
57-
indent_size = 4
58-
59-
[*.appxmanifest]
60-
indent_size = 4
61-
62-
[*.{json,css,webmanifest}]
63-
indent_size = 2
64-
end_of_line = lf
65-
6640
[web.config]
6741
indent_size = 4
6842
end_of_line = lf
6943

70-
[*.sh]
71-
indent_size = 2
72-
end_of_line = lf
73-
7444
[*.cs]
7545
# EOL should be normalized by Git. See https://github.com/dotnet/format/issues/1099
7646
end_of_line = unset

src/DevTKSS.Uno.Samples.MvuxGallery/App.xaml.cs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
using System.Runtime.CompilerServices;
12
using System.Text.Json;
3+
using Microsoft.Extensions.Configuration;
24
using Uno.Resizetizer;
35

46
namespace DevTKSS.Uno.Samples.MvuxGallery;
@@ -59,18 +61,23 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args)
5961
//logBuilder.WebAssemblyLogLevel(LogLevel.Debug);
6062

6163
}, enableUnoLogging: true)
62-
.UseConfiguration(configure: configBuilder =>
63-
configBuilder
64+
.UseConfiguration(
65+
// configureHostConfiguration:
66+
//configure =>
67+
// configure.AddJsonFile("appsettings.sampledata.json", optional: true, reloadOnChange: true),
68+
configure: configBuilder =>
69+
{
70+
return configBuilder
6471
.EmbeddedSource<App>()
6572
.Section<AppConfig>()
66-
6773
.EmbeddedSource<App>("sampledata")
68-
//.Section<DashboardSampleOptions>()
69-
.Section<MainSampleOptions>()
70-
.Section<ListboardSampleOptions>()
71-
.Section<SimpleCardsSampleOptions>()
72-
.Section<CounterSampleOptions>()
73-
)
74+
//.Section<CodeSampleOptions>("DashboardSamples")
75+
.Section<CodeSampleOptions>("NavigationSamples")
76+
.Section<CodeSampleOptions>("ListboardSamples")
77+
.Section<CodeSampleOptions>("SimpleCardsSamples")
78+
.Section<CodeSampleOptions>("CounterSamples");
79+
80+
})
7481
// Enable localization (see appsettings.json for supported languages)
7582
.UseLocalization()
7683
.ConfigureServices((context, services) =>
@@ -79,27 +86,21 @@ protected async override void OnLaunched(LaunchActivatedEventArgs args)
7986

8087
.AddSingleton<IGalleryImageService, GalleryImageService>()
8188

82-
.AddSingleton<ICodeSampleService<MainSampleOptions>, CodeSampleService<MainSampleOptions>>()
83-
.AddSingleton<ICodeSampleService<ListboardSampleOptions>, CodeSampleService<ListboardSampleOptions>>()
84-
.AddSingleton<ICodeSampleService<SimpleCardsSampleOptions>, CodeSampleService<SimpleCardsSampleOptions>>()
85-
.AddSingleton<ICodeSampleService<CounterSampleOptions>, CodeSampleService<CounterSampleOptions>>()
86-
//.AddSingleton<ICodeSampleService<DashboardSampleOptions>, CodeSampleService<DashboardSampleOptions>>()
89+
//.AddNamedConfiguredSingletonCodeService("DashboardSamples")
90+
.AddNamedConfiguredSingletonCodeService("NavigationSamples")
91+
.AddNamedConfiguredSingletonCodeService("ListboardSamples")
92+
.AddNamedConfiguredSingletonCodeService("SimpleCardsSamples")
93+
.AddNamedConfiguredSingletonCodeService("CounterSamples")
8794
)
8895
.UseNavigation(ReactiveViewModelMappings.ViewModelMappings, RegisterRoutes)
8996
.UseSerialization((context, services) =>
9097
services
91-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.CodeSampleOption)
92-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.LinesArray)
93-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.CodeSampleOptionsConfiguration)
94-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.Int32)
95-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.String)
96-
97-
// Following should get removed when NamedOptions can be used with DI Services and really getting values from the configuration
98-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.MainSampleOptions)
99-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.ListboardSampleOptions)
100-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.SimpleCardsSampleOptions)
101-
.AddJsonTypeInfo(CodeSampleOptionContext.Default.CounterSampleOptions)
102-
//.AddJsonTypeInfo(CodeSampleOptionContext.Default.DashboardSampleOptions)
98+
.AddContentSerializer(context)
99+
.AddJsonTypeInfo(CodeSampleOptionsContext.Default.CodeSample)
100+
.AddJsonTypeInfo(CodeSampleOptionsContext.Default.Lines)
101+
.AddJsonTypeInfo(CodeSampleOptionsContext.Default.CodeSampleArray)
102+
.AddJsonTypeInfo(CodeSampleOptionsContext.Default.LinesArray)
103+
.AddJsonTypeInfo(CodeSampleOptionsContext.Default.CodeSampleOptions)
103104

104105
.AddSingleton(new JsonSerializerOptions { PropertyNameCaseInsensitive = true })
105106
)

src/DevTKSS.Uno.Samples.MvuxGallery/DevTKSS.Uno.Samples.MvuxGallery.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Uno.Sdk">
22
<PropertyGroup>
3-
<TargetFrameworks>net9.0-desktop;net9.0-windows10.0.26100</TargetFrameworks>
3+
<TargetFrameworks>net9.0-desktop</TargetFrameworks> <!--;net9.0-windows10.0.26100-->
4+
<!-- BUG: Windows target unable to build when using ResourcesDictionary imported in App.xaml see https://github.com/DevTKSS/DevTKSS.Uno.SampleApps/issues/15 for more information-->
45
<!-- <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>-->
56
<OutputType>Exe</OutputType>
67
<UnoSingleProject>true</UnoSingleProject>
@@ -52,7 +53,7 @@
5253
</ItemGroup>
5354
<ItemGroup>
5455
<UnoImage Include="Assets\Images\*" />
55-
<Resource Include="Assets\Samples\*.txt" CopyToOutputDirectory="PreserveNewest" />
56+
<Resource Include="Assets\Samples\*.txt" CopyToOutputDirectory="PreserveNewest" />
5657
<UnoSplashScreen Include="Assets\SplashScreens\*" />
5758
</ItemGroup>
5859
<ItemGroup>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
2+
public record CodeSample
3+
{
4+
public string SampleID { get; init; } = string.Empty;
5+
public string Description { get; init; } = string.Empty;
6+
public string FilePath { get; init; } = string.Empty;
7+
public Lines[] LineRanges { get; init; } = [];
8+
}
9+
public record Lines
10+
{
11+
public int Start { get; init; }
12+
public int End { get; init; }
13+
}
14+
15+
[JsonSerializable(typeof(CodeSampleOptions))]
16+
[JsonSerializable(typeof(CodeSample))]
17+
[JsonSerializable(typeof(Lines))]
18+
[JsonSerializable(typeof(CodeSample[]))]
19+
public partial class CodeSampleOptionsContext : JsonSerializerContext
20+
{
21+
}

src/DevTKSS.Uno.Samples.MvuxGallery/Models/CodeSamples/CodeSampleOption.cs

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
2+
3+
public record CodeSampleOptions
4+
{
5+
public CodeSample[] Samples { get; init; } = Array.Empty<CodeSample>();
6+
}
7+

src/DevTKSS.Uno.Samples.MvuxGallery/Models/CodeSamples/CodeSampleOptionsConfiguration.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/DevTKSS.Uno.Samples.MvuxGallery/Models/CodeSamples/CodeSampleService.cs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,37 @@
11
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
2-
public partial record CodeSampleService<SampleOptions> : ICodeSampleService<SampleOptions>
3-
where SampleOptions : CodeSampleOptionsConfiguration
4-
{
5-
public CodeSampleService(
6-
IOptions<SampleOptions> options,
7-
ILogger<CodeSampleService<SampleOptions>> logger,
2+
public partial record CodeSampleService : ICodeSampleService
3+
{
4+
private readonly IStorage _storage;
5+
private readonly ILogger<CodeSampleService> _logger;
6+
private readonly string _serviceName;
7+
private CodeSampleOptions _options;
8+
public CodeSampleService(string serviceName,
9+
IOptionsMonitor<CodeSampleOptions> options,
10+
ILogger<CodeSampleService> logger,
811
IStorage storage)
912
{
10-
_options = options.Value;
11-
_logger = logger;
13+
_serviceName = serviceName;
14+
_options = options.Get(_serviceName);
15+
_logger = logger;
1216
_storage = storage;
13-
if (_logger.IsEnabled(LogLevel.Trace))
14-
{
15-
_logger.LogTrace("Initializing options for {serviceName}...",
16-
nameof(CodeSampleService<SampleOptions>));
17-
}
17+
18+
options.OnChange(UpdateOptions);
19+
20+
}
21+
22+
public void UpdateOptions(CodeSampleOptions newOptions, string? changedOption)
23+
{
1824
if (_logger.IsEnabled(LogLevel.Debug))
19-
{
20-
// Log LineRanges for each sample option
21-
foreach (var sample in _options.Samples)
22-
{
23-
_logger.LogDebug("\tSampleID: {sampleID},\nDescription: {description},\nFilePath: {filePath},\nLineRanges: {lineRanges}",
24-
sample.SampleID,
25-
sample.Description,
26-
sample.FilePath,
27-
sample.LineRanges);
28-
29-
}
25+
{
26+
_logger.LogDebug("CodeSampleOptions changed for {name}", changedOption);
3027
}
31-
else if (_logger.IsEnabled(LogLevel.Trace))
28+
if (changedOption == _serviceName)
3229
{
33-
_logger.LogTrace("Gathered {count} Options", _options.Samples.Length);
30+
_logger.LogInformation("Updating CodeSampleOptions for {serviceName}", _serviceName);
31+
_options = newOptions;
3432
}
3533
}
3634

37-
private readonly IStorage _storage;
38-
private readonly ILogger<CodeSampleService<SampleOptions>> _logger;
39-
private readonly SampleOptions _options;
40-
4135
/// <summary>
4236
/// Get a static Collection of Values for <see cref="CodeSampleOptions"/>
4337
/// </summary>
@@ -74,7 +68,7 @@ public async ValueTask<IImmutableList<string>> GetCodeSampleOptionsAsync(Cancell
7468

7569
public async ValueTask<string> GetCodeSampleAsync(string? sampleID, CancellationToken ct = default)
7670
{
77-
if (_options.Samples.FirstOrDefault(sample => sample.SampleID == sampleID) is CodeSampleOption sampleOption)
71+
if (_options.Samples.FirstOrDefault(sample => sample.SampleID == sampleID) is CodeSample sampleOption)
7872
{
7973
if(_logger.IsEnabled(LogLevel.Trace))
8074
{
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11

22
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
33

4-
public interface ICodeSampleService<SampleOptions> where SampleOptions : class
4+
public interface ICodeSampleService
55
{
66
/// <summary>
77
/// Get the content of a specific code sample asynchronously.
88
/// </summary>
99
/// <param name="sampleID">The identifier of the sample.</param>
1010
/// <param name="ct">A cancellation token for the operation.</param>
1111
/// <returns>The content of the code sample.</returns>
12-
ValueTask<string> GetCodeSampleAsync(string sampleID,CancellationToken ct = default);
12+
public ValueTask<string> GetCodeSampleAsync(string sampleID,CancellationToken ct = default);
1313

1414
/// <summary>
1515
/// Get a static collection of values for code sample options asynchronously.
1616
/// </summary>
1717
/// <param name="ct">A cancellation token for the operation.</param>
1818
/// <returns>A list of available code sample options.</returns>
19-
ValueTask<IImmutableList<string>> GetCodeSampleOptionsAsync(CancellationToken ct = default);
19+
public ValueTask<IImmutableList<string>> GetCodeSampleOptionsAsync(CancellationToken ct = default);
2020
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace DevTKSS.Uno.Samples.MvuxGallery.Models.CodeSamples;
2+
3+
/// <summary>
4+
/// Provides extension methods for <see cref="IServiceCollection"/> to register named and configured singleton services for code samples.
5+
/// </summary>
6+
public static class ServiceCollectionExtension
7+
{
8+
/// <summary>
9+
/// Registers a named singleton <see cref="ICodeSampleService"/> with configuration binding for <see cref="CodeSampleOptions"/>.
10+
/// </summary>
11+
/// <param name="services">The <see cref="IServiceCollection"/> to add the service to.</param>
12+
/// <param name="serviceName">The name of the service instance.</param>
13+
/// <param name="sectionName">The optional configuration section name. If not provided, <paramref name="serviceName"/> is used.</param>
14+
/// <returns>The <see cref="IServiceCollection"/> for chaining.</returns>
15+
/// <remarks>
16+
/// This method binds <see cref="CodeSampleOptions"/> to the configuration section "CodeSamples:{sectionName}" and registers
17+
/// a named singleton <see cref="ICodeSampleService"/> using the configured options.
18+
/// </remarks>
19+
public static IServiceCollection AddNamedConfiguredSingletonCodeService(this IServiceCollection services, string serviceName, string? sectionName = null)
20+
{
21+
Console.WriteLine($"ServiceName: {serviceName}");
22+
Console.WriteLine($"SectionName: {sectionName}");
23+
// services.AddOptions<CodeSampleOptions>(sectionName ?? serviceName).BindConfiguration<CodeSampleOptions>(sectionName ?? serviceName);
24+
services.AddNamedSingleton<ICodeSampleService, CodeSampleService>(serviceName, sp => sp
25+
.ConfigureCodeSampleService(sectionName ?? serviceName));
26+
27+
return services;
28+
}
29+
}

0 commit comments

Comments
 (0)