diff --git a/Directory.Packages.props b/Directory.Packages.props
index ae946f6d17..237a523ec7 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -17,12 +17,13 @@
-
+
-
-
@@ -34,11 +35,17 @@
-
+
-
+
diff --git a/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs b/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs
index e9b134734b..d0a935ea98 100644
--- a/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs
+++ b/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs
@@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Concurrent;
+using System.CommandLine;
+using System.CommandLine.Invocation;
using System.Diagnostics;
using ClangSharp;
using ClangSharp.Interop;
@@ -10,6 +12,7 @@
using Microsoft.CodeAnalysis.Text;
using Microsoft.Extensions.Logging;
using Silk.NET.SilkTouch.Caching;
+using Silk.NET.SilkTouch.CommandLine;
using Silk.NET.SilkTouch.Mods;
using Silk.NET.SilkTouch.Sources;
using static ClangSharp.Interop.CXDiagnosticSeverity;
@@ -25,7 +28,6 @@ namespace Silk.NET.SilkTouch.Clang;
///
/// The document factory to use.
/// The configuration to use.
-/// The host configuration to use.
/// The logger to use.
/// The input resolver to use.
/// The mods that modify response files before they are fed to ClangSharp.
@@ -34,15 +36,29 @@ public sealed class ClangScraper(
ResponseFileHandler rspHandler,
DocumentFactory documentFactory,
ClangScraper.Configuration config,
- SilkTouchHostConfiguration hostConfig,
ILogger logger,
IInputResolver inputResolver,
ICacheProvider? cacheProvider = null,
IEnumerable? responseFileMods = null
-) : IMod
+) : IMod, ICommandLineConfigurable
{
// TODO add Windows SDK and Xcode configuration
+ private static Option UseCacheOnlyOption { get; } =
+ new(["--use-cache-only"], () => false)
+ {
+ Description = $"Limits {nameof(ClangScraper)} to only using the cache.",
+ };
+
+ private static Option GenerateCacheOnlyOption { get; } =
+ new(["--generate-cache-only"], () => false)
+ {
+ Description = $"Limits {nameof(ClangScraper)} to only generating the cache.",
+ };
+
+ private bool _useCacheOnly = false;
+ private bool _generateCacheOnly = false;
+
///
/// Configuration for the mod.
///
@@ -88,12 +104,25 @@ public record Configuration
/// Whether this mod should end the generation job after a "generate cache only" run.
///
///
- /// A "generate cache only" run is a run where is set to true.
/// The intended use pattern is setting this to true for the last mod in a job.
///
public bool ExitAfterGenerateCacheOnlyRun { get; init; }
}
+ ///
+ public void RegisterCommandLineOptions(Action register)
+ {
+ register.Invoke(UseCacheOnlyOption);
+ register.Invoke(GenerateCacheOnlyOption);
+ }
+
+ ///
+ public void ReadCommandLineOptions(InvocationContext ctx)
+ {
+ _useCacheOnly = ctx.ParseResult.GetValueForOption(UseCacheOnlyOption);
+ _generateCacheOnly = ctx.ParseResult.GetValueForOption(GenerateCacheOnlyOption);
+ }
+
///
/// Runs ClangSharp to obtain the raw bindings for the given response file.
///
@@ -395,7 +424,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
// Try generating the raw bindings with ClangSharp
// If scraping needs to be skipped or if the scrape fails, then fall back to a cache if available
- var shouldScrape = !hostConfig.UseCacheOnly && config.ScrapeIf.Invoke();
+ var shouldScrape = !_useCacheOnly && config.ScrapeIf.Invoke();
var cacheKey =
resolvedConfig.CacheKey != null
@@ -431,7 +460,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default)
}
}
- if (hostConfig.GenerateCacheOnly)
+ if (_generateCacheOnly)
{
// GenerateCacheOnly is intended to be used when not all caches are available (eg: for multi-platform cache population),
// so we don't validate whether a cache was generated or not in this branch
diff --git a/sources/SilkTouch/SilkTouch/CommandLine/ICommandLineConfigurable.cs b/sources/SilkTouch/SilkTouch/CommandLine/ICommandLineConfigurable.cs
new file mode 100644
index 0000000000..5c678e0d5f
--- /dev/null
+++ b/sources/SilkTouch/SilkTouch/CommandLine/ICommandLineConfigurable.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.CommandLine;
+using System.CommandLine.Invocation;
+
+namespace Silk.NET.SilkTouch.CommandLine;
+
+///
+/// Provides a way to register command line options and read them after they have been parsed.
+///
+public interface ICommandLineConfigurable
+{
+ ///
+ /// Registers the command line options through the provided callback.
+ ///
+ ///
+ /// Options are recommended to be statically defined so they can be deduplicated.
+ ///
+ public void RegisterCommandLineOptions(Action register);
+
+ ///
+ /// Reads the command line options from the provided context.
+ ///
+ public void ReadCommandLineOptions(InvocationContext ctx);
+}
diff --git a/sources/SilkTouch/SilkTouch/Silk.NET.SilkTouch.csproj b/sources/SilkTouch/SilkTouch/Silk.NET.SilkTouch.csproj
index afc4f29d09..c5cf2978db 100644
--- a/sources/SilkTouch/SilkTouch/Silk.NET.SilkTouch.csproj
+++ b/sources/SilkTouch/SilkTouch/Silk.NET.SilkTouch.csproj
@@ -6,8 +6,6 @@
-
-
diff --git a/sources/SilkTouch/SilkTouch/SilkTouchHost.cs b/sources/SilkTouch/SilkTouch/SilkTouchHost.cs
index 144883a650..8072d24483 100644
--- a/sources/SilkTouch/SilkTouch/SilkTouchHost.cs
+++ b/sources/SilkTouch/SilkTouch/SilkTouchHost.cs
@@ -2,18 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.CommandLine;
-using System.CommandLine.Invocation;
using System.Diagnostics.CodeAnalysis;
-using Autofac;
-using Autofac.Extensions.DependencyInjection;
using Microsoft.Build.Locator;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
using Silk.NET.SilkTouch.Caching;
using Silk.NET.SilkTouch.Clang;
+using Silk.NET.SilkTouch.CommandLine;
using Silk.NET.SilkTouch.Mods;
-using Silk.NET.SilkTouch.Mods.Bakery;
using Silk.NET.SilkTouch.Sources;
namespace Silk.NET.SilkTouch;
@@ -46,17 +43,7 @@ public class SilkTouchHost
Description = "Maximum number of parallel jobs.",
};
- private static Option UseCacheOnlyOption { get; } =
- new(["--use-cache-only"], () => false)
- {
- Description = "Limits the generator to only using the cache.",
- };
-
- private static Option GenerateCacheOnlyOption { get; } =
- new(["--generate-cache-only"], () => false)
- {
- Description = "Limits the generator to only generating the cache.",
- };
+ private LogLevel _minimumLogLevel = LogLevel.Information;
private readonly Dictionary _jobDefinitions = [];
@@ -85,86 +72,134 @@ public SilkTouchHost DefineJob(
///
public async Task RunAsync(string[] args)
{
- var rootCommand = new RootCommand
- {
- LoggingOption,
- SkipOption,
- OnlyOption,
- JobsOption,
- UseCacheOnlyOption,
- GenerateCacheOnlyOption,
- };
+ // Register MSBuild
+ MSBuildLocator.RegisterDefaults();
+
+ // Build service provider
+ var services = new ServiceCollection();
+ Configure(services);
+ var provider = services.BuildServiceProvider();
+
+ // Create all jobs
+ var jobs = _jobDefinitions.ToDictionary(
+ jobKvp => jobKvp.Key,
+ jobKvp =>
+ {
+ return new SilkTouchJob(
+ jobKvp.Key,
+ jobKvp.Value.Config,
+ services =>
+ {
+ ConfigureForward(provider, services);
+ jobKvp.Value.Configure.Invoke(services.SilkTouch());
+ }
+ );
+ }
+ );
- rootCommand.SetHandler(async ctx =>
+ try
{
- try
+ // Gather job options
+ var options = new HashSet();
+ foreach (var job in jobs.Values)
{
- // Register MSBuild
- MSBuildLocator.RegisterDefaults();
+ var configurables = job.Provider.GetServices();
+ foreach (var configurable in configurables)
+ {
+ configurable.RegisterCommandLineOptions(option =>
+ {
+ options.Add(option);
+ });
+ }
+ }
- // Build container
- var builder = new ContainerBuilder();
- Configure(builder, ctx);
- await using ILifetimeScope container = builder.Build();
+ var rootCommand = new RootCommand { LoggingOption, SkipOption, OnlyOption, JobsOption };
- var jobKeysToRun = new HashSet(
- ctx.ParseResult.GetValueForOption(OnlyOption) ?? [],
- StringComparer.OrdinalIgnoreCase
- );
+ foreach (var option in options)
+ {
+ rootCommand.Add(option);
+ }
- var jobKeysToSkip = new HashSet(
- ctx.ParseResult.GetValueForOption(SkipOption) ?? [],
- StringComparer.OrdinalIgnoreCase
- );
+ rootCommand.SetHandler(async ctx =>
+ {
+ _minimumLogLevel = ctx.ParseResult.GetValueForOption(LoggingOption);
- var jobsToRun = _jobDefinitions.Where(job =>
+ // Apply job options
+ foreach (var job in jobs.Values)
{
- if (jobKeysToSkip.Contains(job.Key))
+ var configurables = job.Provider.GetServices();
+ foreach (var configurable in configurables)
{
- return false;
+ configurable.ReadCommandLineOptions(ctx);
}
+ }
- return jobKeysToRun.Count == 0 || jobKeysToRun.Contains(job.Key);
- });
-
- var logger = container.Resolve>();
try
{
- await Parallel.ForEachAsync(
- jobsToRun,
- new ParallelOptions
- {
- MaxDegreeOfParallelism = ctx.ParseResult.GetValueForOption(JobsOption),
- },
- async (jobKvp, ct) =>
+ var jobKeysToRun = new HashSet(
+ ctx.ParseResult.GetValueForOption(OnlyOption) ?? [],
+ StringComparer.OrdinalIgnoreCase
+ );
+
+ var jobKeysToSkip = new HashSet(
+ ctx.ParseResult.GetValueForOption(SkipOption) ?? [],
+ StringComparer.OrdinalIgnoreCase
+ );
+
+ var jobsToRun = _jobDefinitions.Keys.Where(jobKey =>
+ {
+ if (jobKeysToSkip.Contains(jobKey))
{
- using var job = new SilkTouchJob(
- jobKvp.Key,
- jobKvp.Value.Config,
- container,
- builder => jobKvp.Value.Configure.Invoke(builder.SilkTouch())
- );
-
- await job.RunAsync(ct);
+ return false;
}
- );
+
+ return jobKeysToRun.Count == 0 || jobKeysToRun.Contains(jobKey);
+ });
+
+ var logger = provider.GetRequiredService>();
+ try
+ {
+ await Parallel.ForEachAsync(
+ jobsToRun,
+ new ParallelOptions
+ {
+ MaxDegreeOfParallelism = ctx.ParseResult.GetValueForOption(
+ JobsOption
+ ),
+ },
+ async (jobKey, ct) =>
+ {
+ var job = jobs[jobKey];
+ await job.RunAsync(ct);
+ }
+ );
+ }
+ catch (Exception e)
+ {
+ logger.LogError(e, "Error occurred while running SilkTouch");
+ throw;
+ }
}
catch (Exception e)
{
- logger.LogError(e, "Error occurred while running SilkTouch");
- throw;
+ Console.WriteLine(e);
+ Exit(1);
}
- }
- catch (Exception e)
+
+ Exit(0);
+ });
+
+ await rootCommand.InvokeAsync(args);
+ }
+ finally
+ {
+ foreach (var job in jobs.Values)
{
- Console.WriteLine(e);
- Exit(1);
+ job.Dispose();
}
- Exit(0);
- });
-
- await rootCommand.InvokeAsync(args);
+ await provider.DisposeAsync();
+ }
}
[DoesNotReturn]
@@ -173,11 +208,12 @@ private static void Exit(int exitCode) =>
Environment.Exit(exitCode);
///
- /// Dependencies defined here will be shared by all jobs.
+ /// Dependencies defined here are only accessible to the host.
+ /// Make them available to the jobs by using .
///
- private void Configure(ContainerBuilder builder, InvocationContext ctx)
+ private void Configure(IServiceCollection services)
{
- var services = new ServiceCollection()
+ services
.AddLogging(builder =>
{
builder.AddSimpleConsole(opts =>
@@ -189,72 +225,46 @@ private void Configure(ContainerBuilder builder, InvocationContext ctx)
opts.IncludeScopes = false;
});
- builder.SetMinimumLevel(ctx.ParseResult.GetValueForOption(LoggingOption));
+ // This avoids depending on the CLI options during container building
+ builder.AddFilter(IsLogLevelEnabled);
})
.AddOptions();
- builder.Populate(services);
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ if (OperatingSystem.IsWindows())
{
- // Create config
- var config = new SilkTouchHostConfiguration()
- {
- UseCacheOnly = ctx.ParseResult.GetValueForOption(UseCacheOnlyOption),
- GenerateCacheOnly = ctx.ParseResult.GetValueForOption(GenerateCacheOnlyOption),
- };
-
- if (config.GenerateCacheOnly && config.UseCacheOnly)
- {
- throw new InvalidOperationException(
- $"{UseCacheOnlyOption.Name} and {GenerateCacheOnlyOption.Name} cannot be enabled at the same time."
- );
- }
-
- builder.RegisterInstance(config).SingleInstance();
-
- builder
- .RegisterType()
- .As()
- .SingleInstance();
-
- builder.RegisterType().SingleInstance();
-
- builder
- .RegisterType()
- .AsSelf()
- .AsImplementedInterfaces()
- .SingleInstance();
-
- builder.RegisterType().As().SingleInstance();
-
- builder.RegisterType().As().SingleInstance();
-
- builder.RegisterType().As().SingleInstance();
+ services.AddSingleton();
+ }
+ else if (OperatingSystem.IsMacOS())
+ {
+ services.AddSingleton();
+ }
+ else
+ {
+ services.AddSingleton();
+ }
+ }
- builder.RegisterType().As().SingleInstance();
+ private bool IsLogLevelEnabled(LogLevel level) => level >= _minimumLogLevel;
- if (OperatingSystem.IsWindows())
- {
- builder
- .RegisterType()
- .As()
- .SingleInstance();
- }
- else if (OperatingSystem.IsMacOS())
- {
- builder
- .RegisterType()
- .As()
- .SingleInstance();
- }
- else
- {
- builder
- .RegisterType()
- .As()
- .SingleInstance();
- }
- }
+ ///
+ /// Dependencies defined here will be available to jobs.
+ ///
+ private void ConfigureForward(IServiceProvider host, IServiceCollection services)
+ {
+ // Prefer to match the registration order above
+ services.AddSingleton(host.GetRequiredService());
+ services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
+
+ services.AddSingleton(host.GetRequiredService());
+ services.AddSingleton(host.GetRequiredService());
+ services.AddSingleton(host.GetRequiredService());
+ services.AddSingleton(host.GetRequiredService());
}
private record JobDefinition(
diff --git a/sources/SilkTouch/SilkTouch/SilkTouchHostConfiguration.cs b/sources/SilkTouch/SilkTouch/SilkTouchHostConfiguration.cs
deleted file mode 100644
index cc897afbfb..0000000000
--- a/sources/SilkTouch/SilkTouch/SilkTouchHostConfiguration.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using Silk.NET.SilkTouch.Clang;
-
-namespace Silk.NET.SilkTouch;
-
-///
-/// Represents the configuration for the shared by multiple bindings generation jobs.
-///
-public record SilkTouchHostConfiguration
-{
- ///
- /// Limits the generator to only using the cache.
- ///
- ///
- /// Currently only affects .
- ///
- public required bool UseCacheOnly { get; init; }
-
- ///
- /// Limits the generator to only generating the cache.
- ///
- ///
- /// Currently only affects .
- ///
- public required bool GenerateCacheOnly { get; init; }
-}
diff --git a/sources/SilkTouch/SilkTouch/SilkTouchJob.cs b/sources/SilkTouch/SilkTouch/SilkTouchJob.cs
index d98398146f..8cf3118bd2 100644
--- a/sources/SilkTouch/SilkTouch/SilkTouchJob.cs
+++ b/sources/SilkTouch/SilkTouch/SilkTouchJob.cs
@@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
-using Autofac;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using Silk.NET.SilkTouch.Clang;
using Silk.NET.SilkTouch.Mods;
+using Silk.NET.SilkTouch.Mods.Bakery;
using Silk.NET.SilkTouch.Mods.Transformation;
using Silk.NET.SilkTouch.Sources;
using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
@@ -16,8 +18,6 @@ namespace Silk.NET.SilkTouch;
///
internal class SilkTouchJob : IDisposable
{
- private readonly ILifetimeScope _container;
-
private readonly ILogger _logger;
private readonly IInputResolver _inputResolver;
private readonly IModContextFactory _modContextFactory;
@@ -34,45 +34,51 @@ internal class SilkTouchJob : IDisposable
public SilkTouchConfiguration Config { get; private set; }
///
- /// Gets the loaded mods for this generator instance.
+ /// Gets the loaded mods for this job.
///
public IReadOnlyList Mods { get; }
+ ///
+ /// The service provider for this job.
+ ///
+ public ServiceProvider Provider;
+
///
/// Creates a new .
///
/// The job key.
/// The job config.
- /// The parent container. Should be the one from the .
///
- /// The action that configures the dependency container used by this job.
+ /// The action that configures the services used by this job.
/// You'll want to register SilkTouch mods during this action. See .
///
public SilkTouchJob(
string key,
SilkTouchConfiguration config,
- ILifetimeScope parentContainer,
- Action configure
+ Action configure
)
{
Key = key;
Config = config;
- _logger = parentContainer.Resolve>();
- _inputResolver = parentContainer.Resolve();
- _container = parentContainer.BeginLifetimeScope(builder =>
+ var services = new ServiceCollection();
{
// Register default dependencies
- builder.RegisterType().SingleInstance();
- builder.RegisterType().SingleInstance();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
// Register user defined dependencies
- configure.Invoke(builder);
- });
+ configure.Invoke(services);
+ }
- _modContextFactory = _container.Resolve();
- _documentFactory = _container.Resolve();
- Mods = _container.Resolve();
+ Provider = services.BuildServiceProvider();
+ _logger = Provider.GetRequiredService>();
+ _inputResolver = Provider.GetRequiredService();
+ _modContextFactory = Provider.GetRequiredService();
+ _documentFactory = Provider.GetRequiredService();
+ Mods = Provider.GetRequiredService>().ToArray();
}
///
@@ -175,5 +181,5 @@ await File.ReadAllTextAsync(Config.DefaultLicenseHeader, ct)
}
///
- public void Dispose() => _container.Dispose();
+ public void Dispose() => Provider.Dispose();
}
diff --git a/sources/SilkTouch/SilkTouch/SilkTouchRegistrationExtensions.cs b/sources/SilkTouch/SilkTouch/SilkTouchRegistrationExtensions.cs
index c6dc9061ba..7b397ccac5 100644
--- a/sources/SilkTouch/SilkTouch/SilkTouchRegistrationExtensions.cs
+++ b/sources/SilkTouch/SilkTouch/SilkTouchRegistrationExtensions.cs
@@ -1,8 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using Autofac;
-using Autofac.Builder;
+using Microsoft.Extensions.DependencyInjection;
using Silk.NET.SilkTouch.Clang;
using Silk.NET.SilkTouch.Mods;
using Silk.NET.SilkTouch.Mods.Transformation;
@@ -18,8 +17,8 @@ public static class SilkTouchRegistrationExtensions
/// Entrypoint to the rest of the SilkTouch registration methods.
/// Begins a .
///
- public static SilkTouchRegistrationContext SilkTouch(this ContainerBuilder builder) =>
- new(builder);
+ public static SilkTouchRegistrationContext SilkTouch(this IServiceCollection services) =>
+ new(services);
// Non-mods
extension(SilkTouchRegistrationContext context)
@@ -42,11 +41,7 @@ public SilkTouchRegistrationContext WithDefaultFunctionTransformers(
///
public SilkTouchRegistrationContext WithPtrRefTransformer()
{
- context
- .Builder.RegisterType()
- .AsImplementedInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsInterfaces();
return context;
}
@@ -58,17 +53,9 @@ public SilkTouchRegistrationContext WithBoolTransformer(
BoolTransformer.Configuration? boolTransformerConfig = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(
- typeof(BoolTransformer.Configuration),
- boolTransformerConfig ?? new()
- )
- )
- .AsImplementedInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsInterfaces(
+ boolTransformerConfig ?? new()
+ );
return context;
}
@@ -78,11 +65,7 @@ public SilkTouchRegistrationContext WithBoolTransformer(
///
public SilkTouchRegistrationContext WithArrayParameterTransformer()
{
- context
- .Builder.RegisterType()
- .AsImplementedInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsInterfaces();
return context;
}
}
@@ -97,14 +80,7 @@ public SilkTouchRegistrationContext AddApiProfiles(
AddApiProfiles.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(AddApiProfiles.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -113,12 +89,7 @@ public SilkTouchRegistrationContext AddApiProfiles(
///
public SilkTouchRegistrationContext ClangScraper(ClangScraper.Configuration config)
{
- context
- .Builder.RegisterType()
- .WithParameter(new TypedParameter(typeof(ClangScraper.Configuration), config))
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -127,14 +98,7 @@ public SilkTouchRegistrationContext ClangScraper(ClangScraper.Configuration conf
///
public SilkTouchRegistrationContext AddIncludes(AddIncludes.Configuration? config = null)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(AddIncludes.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -143,12 +107,7 @@ public SilkTouchRegistrationContext AddIncludes(AddIncludes.Configuration? confi
///
public SilkTouchRegistrationContext AddOpaqueStructs(AddOpaqueStructs.Configuration config)
{
- context
- .Builder.RegisterType()
- .WithParameter(new TypedParameter(typeof(AddOpaqueStructs.Configuration), config))
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -157,14 +116,7 @@ public SilkTouchRegistrationContext AddOpaqueStructs(AddOpaqueStructs.Configurat
///
public SilkTouchRegistrationContext AddVTables(AddVTables.Configuration? config = null)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(AddVTables.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -173,12 +125,7 @@ public SilkTouchRegistrationContext AddVTables(AddVTables.Configuration? config
///
public SilkTouchRegistrationContext BakeSourceSets(BakeSourceSets.Configuration config)
{
- context
- .Builder.RegisterType()
- .WithParameter(new TypedParameter(typeof(BakeSourceSets.Configuration), config))
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -187,12 +134,7 @@ public SilkTouchRegistrationContext BakeSourceSets(BakeSourceSets.Configuration
///
public SilkTouchRegistrationContext ChangeNamespace(ChangeNamespace.Configuration config)
{
- context
- .Builder.RegisterType()
- .WithParameter(new TypedParameter(typeof(ChangeNamespace.Configuration), config))
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -203,12 +145,7 @@ public SilkTouchRegistrationContext ChangeNativeClass(
ChangeNativeClass.Configuration config
)
{
- context
- .Builder.RegisterType()
- .WithParameter(new TypedParameter(typeof(ChangeNativeClass.Configuration), config))
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -217,11 +154,7 @@ ChangeNativeClass.Configuration config
///
public SilkTouchRegistrationContext ExtractEnumConstants()
{
- context
- .Builder.RegisterType()
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces();
return context;
}
@@ -230,11 +163,7 @@ public SilkTouchRegistrationContext ExtractEnumConstants()
///
public SilkTouchRegistrationContext ExtractFunctionPointers()
{
- context
- .Builder.RegisterType()
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces();
return context;
}
@@ -243,11 +172,7 @@ public SilkTouchRegistrationContext ExtractFunctionPointers()
///
public SilkTouchRegistrationContext ExtractHandles()
{
- context
- .Builder.RegisterType()
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces();
return context;
}
@@ -256,11 +181,7 @@ public SilkTouchRegistrationContext ExtractHandles()
///
public SilkTouchRegistrationContext ExtractNestedTypes()
{
- context
- .Builder.RegisterType()
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces();
return context;
}
@@ -271,14 +192,7 @@ public SilkTouchRegistrationContext IdentifySharedPrefixes(
IdentifySharedPrefixes.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(IdentifySharedPrefixes.Configuration), config)
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -289,14 +203,7 @@ public SilkTouchRegistrationContext InterceptNativeFunctions(
InterceptNativeFunctions.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(InterceptNativeFunctions.Configuration), config)
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
@@ -305,11 +212,7 @@ public SilkTouchRegistrationContext InterceptNativeFunctions(
///
public SilkTouchRegistrationContext MarkNativeNames()
{
- context
- .Builder.RegisterType()
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces();
return context;
}
@@ -320,14 +223,7 @@ public SilkTouchRegistrationContext MixKhronosData(
MixKhronosData.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(MixKhronosData.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -338,14 +234,7 @@ public SilkTouchRegistrationContext PrettifyNames(
PrettifyNames.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(PrettifyNames.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -356,14 +245,7 @@ public SilkTouchRegistrationContext StripAttributes(
StripAttributes.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(StripAttributes.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -374,14 +256,7 @@ public SilkTouchRegistrationContext TransformEnums(
TransformEnums.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(TransformEnums.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config ?? new());
return context;
}
@@ -390,11 +265,7 @@ public SilkTouchRegistrationContext TransformEnums(
///
public SilkTouchRegistrationContext TransformFunctions()
{
- context
- .Builder.RegisterType()
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces();
return context;
}
@@ -405,14 +276,9 @@ public SilkTouchRegistrationContext TransformHandles(
TransformHandles.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(TransformHandles.Configuration), config ?? new())
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(
+ config ?? new()
+ );
return context;
}
@@ -423,46 +289,58 @@ public SilkTouchRegistrationContext TransformProperties(
TransformProperties.Configuration? config = null
)
{
- context
- .Builder.RegisterType()
- .WithParameter(
- new TypedParameter(typeof(TransformProperties.Configuration), config)
- )
- .AsHierarchyAndInterfaces()
- .SingleInstance();
-
+ context.Services.AddSingletonAsHierarchyAndInterfaces(config);
return context;
}
}
- extension(
- IRegistrationBuilder registration
- )
- where TConcreteActivatorData : IConcreteActivatorData
+ extension(IServiceCollection services)
{
- private IRegistrationBuilder<
- TLimit,
- TConcreteActivatorData,
- SingleRegistrationStyle
- > AsHierarchyAndInterfaces()
- {
- var type = registration.ActivatorData.Activator.LimitType;
- var typesToRegister = new HashSet();
- typesToRegister.UnionWith(type.GetInterfaces());
+ private IServiceCollection AddSingletonAsInterfaces(object? parameter = null)
+ where T : class => services.AddSingletonAs(typeof(T).GetInterfaces(), parameter);
- var current = type;
+ private IServiceCollection AddSingletonAsHierarchyAndInterfaces(object? parameter = null)
+ where T : class
+ {
+ var types = new HashSet(typeof(T).GetInterfaces());
+ var current = typeof(T);
while (current != null)
{
- typesToRegister.Add(current);
+ types.Add(current);
current = current.BaseType;
}
- return registration.As(typesToRegister.ToArray());
+ return services.AddSingletonAs(types, parameter);
+ }
+
+ private IServiceCollection AddSingletonAs(IEnumerable types, object? parameter)
+ where T : class
+ {
+ var key = new object();
+ object[] parameters = parameter is null ? [] : [parameter];
+
+ services.AddKeyedSingleton(
+ typeof(T),
+ key,
+ (sp, _) => ActivatorUtilities.CreateInstance(sp, parameters)
+ );
+
+ services.AddSingleton(typeof(T), sp => sp.GetRequiredKeyedService(key));
+
+ foreach (var type in types)
+ {
+ if (type != typeof(T))
+ {
+ services.AddSingleton(type, sp => sp.GetRequiredKeyedService(key));
+ }
+ }
+
+ return services;
}
}
///
- /// Helper for registering SilkTouch to a
+ /// Helper for registering SilkTouch to a
///
- public record struct SilkTouchRegistrationContext(ContainerBuilder Builder);
+ public record struct SilkTouchRegistrationContext(IServiceCollection Services);
}