Skip to content

Commit 9967f18

Browse files
authored
Feature Add ReactiveUI modules and builder extensions for Splat (#1372)
* Add DI modules and builder extensions for Splat Introduces IReactiveUIModule interface and implementation modules for Autofac, DryIoc, Exceptionless, Microsoft.Extensions.DependencyInjection, Ninject, and SimpleInjector. Adds SplatBuilderExtensions for applying modules to the Splat dependency resolver, enabling AOT-compatible service registration. * Change Namespace * IReactiveUIModule => IModule
1 parent a17b233 commit 9967f18

File tree

10 files changed

+221
-0
lines changed

10 files changed

+221
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using Autofac;
7+
using Splat.Autofac;
8+
9+
namespace Splat.Builder;
10+
11+
/// <summary>
12+
/// Splat module for configuring the Autofac dependency resolver.
13+
/// </summary>
14+
/// <remarks>
15+
/// Initializes a new instance of the <see cref="AutofacSplatModule"/> class.
16+
/// </remarks>
17+
/// <param name="builder">The Autofac container builder.</param>
18+
public sealed class AutofacSplatModule(ContainerBuilder builder) : IModule
19+
{
20+
private readonly ContainerBuilder _builder = builder ?? throw new ArgumentNullException(nameof(builder));
21+
22+
/// <inheritdoc />
23+
public void Configure(IMutableDependencyResolver resolver)
24+
{
25+
var autofacResolver = _builder.UseAutofacDependencyResolver();
26+
27+
// Also register the resolver instance for later retrieval if the container is built after
28+
_builder.RegisterInstance(autofacResolver);
29+
}
30+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using DryIoc;
7+
using Splat.DryIoc;
8+
9+
namespace Splat.Builder;
10+
11+
/// <summary>
12+
/// Splat module for configuring the DryIoc dependency resolver.
13+
/// </summary>
14+
/// <remarks>
15+
/// Initializes a new instance of the <see cref="DryIocSplatModule"/> class.
16+
/// </remarks>
17+
/// <param name="container">The DryIoc container.</param>
18+
public sealed class DryIocSplatModule(IContainer container) : IModule
19+
{
20+
private readonly IContainer _container = container ?? throw new ArgumentNullException(nameof(container));
21+
22+
/// <inheritdoc />
23+
public void Configure(IMutableDependencyResolver resolver) => _container.UseDryIocDependencyResolver();
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using Exceptionless;
7+
using Splat;
8+
using Splat.Exceptionless;
9+
10+
namespace Splat.Builder;
11+
12+
/// <summary>
13+
/// Splat module for configuring the Exceptionless dependency resolver.
14+
/// </summary>
15+
/// <remarks>
16+
/// Initializes a new instance of the <see cref="ExceptionlessSplatModule"/> class.
17+
/// </remarks>
18+
/// <param name="exceptionlessClient">The Exceptionless container.</param>
19+
public sealed class ExceptionlessSplatModule(ExceptionlessClient exceptionlessClient) : IModule
20+
{
21+
private readonly ExceptionlessClient _container = exceptionlessClient ?? throw new ArgumentNullException(nameof(exceptionlessClient));
22+
23+
/// <inheritdoc />
24+
public void Configure(IMutableDependencyResolver resolver) => resolver.UseExceptionlessWithWrappingFullLogger(_container);
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using Microsoft.Extensions.DependencyInjection;
7+
using Splat.Microsoft.Extensions.DependencyInjection;
8+
9+
namespace Splat.Builder;
10+
11+
/// <summary>
12+
/// Splat module for configuring the Microsoft dependency resolver.
13+
/// </summary>
14+
/// <seealso cref="IModule" />
15+
public sealed class MicrosoftDependencyResolverModule(IServiceCollection serviceCollection) : IModule
16+
{
17+
private readonly IServiceCollection _container = serviceCollection ?? throw new ArgumentNullException(nameof(serviceCollection));
18+
19+
/// <inheritdoc />
20+
public void Configure(IMutableDependencyResolver resolver) => _container.UseMicrosoftDependencyResolver();
21+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using Ninject;
7+
using Splat.Ninject;
8+
9+
namespace Splat.Builder;
10+
11+
/// <summary>
12+
/// Splat module for configuring the Ninject dependency resolver.
13+
/// </summary>
14+
/// <remarks>
15+
/// Initializes a new instance of the <see cref="NinjectSplatModule"/> class.
16+
/// </remarks>
17+
/// <param name="kernel">The Ninject container.</param>
18+
public sealed class NinjectSplatModule(IKernel kernel) : IModule
19+
{
20+
private readonly IKernel _container = kernel ?? throw new ArgumentNullException(nameof(kernel));
21+
22+
/// <inheritdoc />
23+
public void Configure(IMutableDependencyResolver resolver) => _container.UseNinjectDependencyResolver();
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using SimpleInjector;
7+
using Splat.SimpleInjector;
8+
9+
namespace Splat.Builder;
10+
11+
/// <summary>
12+
/// Splat module for configuring the SimpleInjector dependency resolver.
13+
/// </summary>
14+
/// <seealso cref="IModule" />
15+
/// <remarks>
16+
/// Initializes a new instance of the <see cref="SimpleInjectorSplatModule" /> class.
17+
/// </remarks>
18+
/// <param name="container">The SimpleInjector container.</param>
19+
/// <param name="initializer">The SimpleInjector Initializer.</param>
20+
public sealed class SimpleInjectorSplatModule(Container container, SimpleInjectorInitializer initializer) : IModule
21+
{
22+
private readonly Container _container = container ?? throw new ArgumentNullException(nameof(container));
23+
24+
/// <inheritdoc />
25+
public void Configure(IMutableDependencyResolver resolver) => _container.UseSimpleInjectorDependencyResolver(initializer);
26+
}

src/Splat.Tests/API/ApiApprovalTests.SplatProject.DotNet8_0.verified.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,17 @@ namespace Splat.ApplicationPerformanceMonitoring
773773
void OnViewNavigation(string name);
774774
}
775775
}
776+
namespace Splat.Builder
777+
{
778+
public interface IModule
779+
{
780+
void Configure(Splat.IMutableDependencyResolver resolver);
781+
}
782+
public static class SplatBuilderExtensions
783+
{
784+
public static void Apply(this Splat.Builder.IModule module) { }
785+
}
786+
}
776787
namespace Splat.ModeDetection
777788
{
778789
public sealed class Mode : Splat.IModeDetector

src/Splat.Tests/API/ApiApprovalTests.SplatProject.DotNet9_0.verified.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,17 @@ namespace Splat.ApplicationPerformanceMonitoring
773773
void OnViewNavigation(string name);
774774
}
775775
}
776+
namespace Splat.Builder
777+
{
778+
public interface IModule
779+
{
780+
void Configure(Splat.IMutableDependencyResolver resolver);
781+
}
782+
public static class SplatBuilderExtensions
783+
{
784+
public static void Apply(this Splat.Builder.IModule module) { }
785+
}
786+
}
776787
namespace Splat.ModeDetection
777788
{
778789
public sealed class Mode : Splat.IModeDetector

src/Splat/Builder/IModule.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using Splat;
7+
8+
namespace Splat.Builder;
9+
10+
/// <summary>
11+
/// Defines a contract for ReactiveUI modules that can configure dependency injection.
12+
/// This provides an AOT-compatible way to register services.
13+
/// </summary>
14+
public interface IModule
15+
{
16+
/// <summary>
17+
/// Configures the dependency resolver with the module's services.
18+
/// </summary>
19+
/// <param name="resolver">The dependency resolver to configure.</param>
20+
void Configure(IMutableDependencyResolver resolver);
21+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (c) 2025 ReactiveUI. All rights reserved.
2+
// Licensed to ReactiveUI under one or more agreements.
3+
// ReactiveUI licenses this file to you under the MIT license.
4+
// See the LICENSE file in the project root for full license information.
5+
6+
using System;
7+
8+
namespace Splat.Builder;
9+
10+
/// <summary>
11+
/// Common extension helpers for registering Splat modules.
12+
/// </summary>
13+
public static class SplatBuilderExtensions
14+
{
15+
/// <summary>
16+
/// Runs the provided configuration action imediately against the current Splat Locator.
17+
/// </summary>
18+
/// <param name="module">The module to configure.</param>
19+
public static void Apply(this IModule module)
20+
{
21+
if (module is null)
22+
{
23+
throw new ArgumentNullException(nameof(module));
24+
}
25+
26+
module.Configure(Locator.CurrentMutable);
27+
}
28+
}

0 commit comments

Comments
 (0)