Skip to content

Commit 19a9120

Browse files
authored
Update version from 11.3.4 to 11.3.0 (#21)
* Update version from 11.3.4 to 11.3.7 * Refactor DI integration to use external Splat packages Replaces internal Autofac, DryIoc, and Microsoft.Extensions.DependencyInjection dependency resolver implementations with the corresponding Splat.* packages. Updates AppBuilder extension methods to use new Splat APIs and removes obsolete code. Centralizes package version management and updates test projects and usages to reflect the new DI integration approach. * Rename Splat.Avalonia.* to ReactiveUI.Avalonia.* and extend DI mixins Renamed all Splat.Avalonia.* projects, files, and namespaces to ReactiveUI.Avalonia.* equivalents. Enhanced DI mixins for Autofac, DryIoc, Ninject, and Microsoft.Extensions.DependencyInjection to support additional configuration and builder hooks. Updated solution and test project references to match new naming. Adjusted InternalsVisibleTo attributes for new test project names. * Update ReactiveUI.Avalonia.Tests.csproj * Add tests for Autofac and Ninject Avalonia mixins Introduces unit tests for Autofac and Ninject integration with Avalonia's ReactiveUI mixins, including null argument checks and builder return validation. Updates the test project to reference Autofac and Ninject projects with appropriate aliases. * Refactor DI container mixins and update README setup docs Refactored DI container extension methods for Autofac, DryIoc, Microsoft.Extensions.DependencyInjection, and Ninject to use consistent namespaces and signatures. Updated the README with improved setup instructions, usage examples, and API documentation for all supported DI containers. Adjusted related tests to match new namespaces and method signatures. * Add tests for DI container and view registration APIs Introduces new test classes covering AppBuilder extension methods for DI container integration (DryIoc, Microsoft.Extensions.DependencyInjection, and generic containers) and ReactiveUI view registration. These tests verify correct builder return values, null handling, and registration logic for the relevant extension methods. * Update version from 11.3.0 to 11.3
1 parent a11beb7 commit 19a9120

File tree

89 files changed

+2939
-3482
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+2939
-3482
lines changed

README.md

Lines changed: 292 additions & 100 deletions
Large diffs are not rendered by default.

src/Directory.Packages.props

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,37 @@
22
<PropertyGroup>
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
44
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
5+
<AvaloniaVersion>11.3.0</AvaloniaVersion>
6+
<AvaloniaLatestVersion>11.3.*</AvaloniaLatestVersion>
7+
<SplatVersion>17.1.1</SplatVersion>
58
</PropertyGroup>
69
<ItemGroup>
710
<PackageVersion Include="coverlet.collector" Version="6.0.4">
811
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
912
<PrivateAssets>all</PrivateAssets>
1013
</PackageVersion>
1114
<PackageVersion Include="coverlet.msbuild" Version="6.0.4" />
12-
<PackageVersion Include="Autofac" Version="8.4.0" />
13-
<PackageVersion Include="Avalonia" Version="11.3.7" />
14-
<PackageVersion Include="Avalonia.Desktop" Version="11.3.7" />
15-
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.7" />
16-
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.7" />
17-
<PackageVersion Include="DryIoc.Dll" Version="5.4.3" />
18-
<PackageVersion Include="DynamicData" Version="9.4.1" />
15+
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)" />
16+
<PackageVersion Include="Avalonia.Desktop" Version="$(AvaloniaVersion)" />
17+
<PackageVersion Include="Avalonia.Fonts.Inter" Version="$(AvaloniaVersion)" />
18+
<PackageVersion Include="Avalonia.Themes.Fluent" Version="$(AvaloniaVersion)" />
1919
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
2020
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
21-
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.9" />
2221
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
2322
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
2423
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.8.118" />
25-
<PackageVersion Include="Ninject" Version="3.3.6" />
2624
<PackageVersion Include="ReactiveUI" Version="22.0.1" />
2725
<PackageVersion Include="Roslynator.Analyzers" Version="4.14.0" />
28-
<PackageVersion Include="Splat" Version="17.1.1" />
29-
<PackageVersion Include="Splat.Autofac" Version="17.1.1" />
30-
<PackageVersion Include="Splat.Drawing" Version="17.1.1" />
31-
<PackageVersion Include="Splat.DryIoc" Version="17.1.1" />
32-
<PackageVersion Include="Splat.Ninject" Version="17.1.1" />
26+
<PackageVersion Include="Splat" Version="$(SplatVersion)" />
27+
<PackageVersion Include="Splat.Autofac" Version="$(SplatVersion)" />
28+
<PackageVersion Include="Splat.Drawing" Version="$(SplatVersion)" />
29+
<PackageVersion Include="Splat.DryIoc" Version="$(SplatVersion)" />
30+
<PackageVersion Include="Splat.Microsoft.Extensions.DependencyInjection" Version="$(SplatVersion)" />
31+
<PackageVersion Include="Splat.Ninject" Version="$(SplatVersion)" />
3332
<PackageVersion Include="stylecop.analyzers" Version="1.2.0-beta.556" />
3433
<PackageVersion Include="System.Collections.Immutable" Version="9.0.9" />
3534
<PackageVersion Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
3635
<PackageVersion Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
37-
<PackageVersion Include="System.Text.Json" Version="9.0.9" />
3836
<PackageVersion Include="NUnit" Version="4.4.0" />
3937
<PackageVersion Include="NUnit3TestAdapter" Version="5.1.0" />
4038
<PackageVersion Include="NUnit.Analyzers" Version="4.10.0" />
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation 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 ReactiveUI.Builder;
8+
using Splat;
9+
using Splat.Autofac;
10+
using Splat.Builder;
11+
using AppBuilder = Avalonia.AppBuilder;
12+
13+
namespace ReactiveUI.Avalonia.Splat;
14+
15+
/// <summary>
16+
/// Avalonia Mixins.
17+
/// </summary>
18+
public static class AvaloniaMixins
19+
{
20+
/// <summary>
21+
/// Uses the splat with dry ioc.
22+
/// </summary>
23+
/// <param name="builder">The builder.</param>
24+
/// <param name="containerConfig">The configure.</param>
25+
/// <param name="withResolver">The get resolver.</param>
26+
/// <returns>
27+
/// An App Builder.
28+
/// </returns>
29+
/// <exception cref="System.ArgumentNullException">builder.</exception>
30+
public static AppBuilder UseReactiveUIWithAutofac(this AppBuilder builder, Action<ContainerBuilder> containerConfig, Action<AutofacDependencyResolver>? withResolver = null) =>
31+
builder switch
32+
{
33+
null => throw new ArgumentNullException(nameof(builder)),
34+
_ => builder.UseReactiveUI().AfterPlatformServicesSetup(_ =>
35+
{
36+
if (AppLocator.CurrentMutable is null)
37+
{
38+
return;
39+
}
40+
#if NETSTANDARD
41+
if (containerConfig is null)
42+
{
43+
throw new ArgumentNullException(nameof(containerConfig));
44+
}
45+
#else
46+
ArgumentNullException.ThrowIfNull(containerConfig);
47+
#endif
48+
var containerBuilder = new ContainerBuilder();
49+
var autofacResolver = containerBuilder.UseAutofacDependencyResolver();
50+
containerBuilder.RegisterInstance(autofacResolver);
51+
autofacResolver.InitializeReactiveUI(RegistrationNamespace.Avalonia);
52+
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
53+
containerConfig(containerBuilder);
54+
var container = containerBuilder.Build();
55+
autofacResolver.SetLifetimeScope(container);
56+
57+
if (withResolver is not null)
58+
{
59+
withResolver(autofacResolver);
60+
}
61+
})
62+
};
63+
64+
/// <summary>
65+
/// Uses the reactive UI with autofac.
66+
/// </summary>
67+
/// <param name="builder">The builder.</param>
68+
/// <param name="containerConfig">The container configuration.</param>
69+
/// <param name="withResolver">The with resolver.</param>
70+
/// <param name="withReactiveUIBuilder">The with reactive UI builder.</param>
71+
/// <returns>
72+
/// An App Builder.
73+
/// </returns>
74+
/// <exception cref="ArgumentNullException">builder.</exception>
75+
public static AppBuilder UseReactiveUIWithAutofac(this AppBuilder builder, Action<ContainerBuilder> containerConfig, Action<AutofacDependencyResolver>? withResolver = null, Action<ReactiveUIBuilder>? withReactiveUIBuilder = null)
76+
{
77+
if (builder is null)
78+
{
79+
throw new ArgumentNullException(nameof(builder));
80+
}
81+
82+
if (containerConfig is null)
83+
{
84+
throw new ArgumentNullException(nameof(containerConfig));
85+
}
86+
87+
return builder.UseReactiveUI(rxuiBuilder =>
88+
{
89+
var containerBuilder = new ContainerBuilder();
90+
rxuiBuilder.UsingSplatModule(new AutofacSplatModule(containerBuilder));
91+
containerConfig(containerBuilder);
92+
var container = containerBuilder.Build();
93+
var autofacResolver = container.Resolve<AutofacDependencyResolver>();
94+
autofacResolver.SetLifetimeScope(container);
95+
if (withResolver is not null)
96+
{
97+
withResolver(autofacResolver);
98+
}
99+
100+
if (withReactiveUIBuilder is not null)
101+
{
102+
withReactiveUIBuilder(rxuiBuilder);
103+
}
104+
});
105+
}
106+
}

src/Splat.Avalonia.Autofac/Splat.Avalonia.Autofac.csproj renamed to src/ReactiveUI.Avalonia.Autofac/ReactiveUI.Avalonia.Autofac.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
<PackageTags>mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;avalonia;net;netcore</PackageTags>
99
</PropertyGroup>
1010
<ItemGroup>
11-
<PackageReference Include="Autofac" />
12-
<PackageReference Include="System.Text.Json" />
11+
<PackageReference Include="Splat.Autofac" />
1312
<ProjectReference Include="..\ReactiveUI.Avalonia\ReactiveUI.Avalonia.csproj" />
1413
</ItemGroup>
1514
</Project>
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
2+
// Licensed to the .NET Foundation under one or more agreements.
3+
// The .NET Foundation 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 ReactiveUI.Builder;
8+
using Splat;
9+
using Splat.Builder;
10+
using Splat.DryIoc;
11+
using AppBuilder = Avalonia.AppBuilder;
12+
13+
namespace ReactiveUI.Avalonia.Splat;
14+
15+
/// <summary>
16+
/// Avalonia Mixins.
17+
/// </summary>
18+
public static class AvaloniaMixins
19+
{
20+
/// <summary>
21+
/// Uses the splat with dry ioc.
22+
/// </summary>
23+
/// <param name="builder">The builder.</param>
24+
/// <param name="containerConfig">The configure.</param>
25+
/// <returns>An App Builder.</returns>
26+
public static AppBuilder UseReactiveUIWithDryIoc(this AppBuilder builder, Action<Container> containerConfig) =>
27+
builder switch
28+
{
29+
null => throw new ArgumentNullException(nameof(builder)),
30+
_ => builder.UseReactiveUI().AfterPlatformServicesSetup(_ =>
31+
{
32+
if (AppLocator.CurrentMutable is null)
33+
{
34+
return;
35+
}
36+
37+
#if NETSTANDARD
38+
if (containerConfig is null)
39+
{
40+
throw new ArgumentNullException(nameof(containerConfig));
41+
}
42+
#else
43+
ArgumentNullException.ThrowIfNull(containerConfig);
44+
#endif
45+
46+
var container = new Container();
47+
container.UseDryIocDependencyResolver();
48+
AppLocator.CurrentMutable.RegisterConstant(container);
49+
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
50+
containerConfig(container);
51+
})
52+
};
53+
54+
/// <summary>
55+
/// Uses the reactive UI with dry ioc.
56+
/// </summary>
57+
/// <param name="builder">The builder.</param>
58+
/// <param name="containerConfig">The container configuration.</param>
59+
/// <param name="withReactiveUIBuilder">The with reactive UI builder.</param>
60+
/// <returns>An App Builder.</returns>
61+
/// <exception cref="ArgumentNullException">builder.</exception>
62+
public static AppBuilder UseReactiveUIWithDryIoc(this AppBuilder builder, Action<Container> containerConfig, Action<ReactiveUIBuilder>? withReactiveUIBuilder = null) =>
63+
builder switch
64+
{
65+
null => throw new ArgumentNullException(nameof(builder)),
66+
_ => builder.UseReactiveUI(rxuiBuilder =>
67+
{
68+
#if NETSTANDARD
69+
if (containerConfig is null)
70+
{
71+
throw new ArgumentNullException(nameof(containerConfig));
72+
}
73+
#else
74+
ArgumentNullException.ThrowIfNull(containerConfig);
75+
#endif
76+
77+
var container = new Container();
78+
rxuiBuilder.UsingSplatModule(new DryIocSplatModule(container));
79+
AppLocator.CurrentMutable.RegisterConstant(container);
80+
containerConfig(container);
81+
82+
if (withReactiveUIBuilder is not null)
83+
{
84+
withReactiveUIBuilder(rxuiBuilder);
85+
}
86+
})
87+
};
88+
}

src/Splat.Avalonia.DryIoc/Splat.Avalonia.DryIoc.csproj renamed to src/ReactiveUI.Avalonia.DryIoc/ReactiveUI.Avalonia.DryIoc.csproj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
<PackageTags>mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;avalonia;net;netcore</PackageTags>
99
</PropertyGroup>
1010
<ItemGroup>
11-
<PackageReference Include="DryIoc.Dll" />
12-
<PackageReference Include="System.Text.Json" />
11+
<PackageReference Include="Splat.DryIoc" />
1312
</ItemGroup>
1413
<ItemGroup>
1514
<ProjectReference Include="..\ReactiveUI.Avalonia\ReactiveUI.Avalonia.csproj" />
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Avalonia;
2+
using DryIoc;
3+
using NUnit.Framework;
4+
using ReactiveUI.Avalonia.Splat;
5+
using Splat.DryIoc;
6+
7+
namespace ReactiveUI.Avalonia.DryIoc.Tests;
8+
9+
public class AvaloniaMixinsDryIocMoreTests
10+
{
11+
[Test]
12+
public void UseReactiveUIWithDryIoc_WithBuilderOverload_Returns_Builder()
13+
{
14+
var builder = AppBuilder.Configure<Application>();
15+
var result = AvaloniaMixins.UseReactiveUIWithDryIoc(
16+
builder,
17+
containerConfig: c =>
18+
{
19+
c.RegisterInstance(new object());
20+
},
21+
withReactiveUIBuilder: _ => { });
22+
23+
Assert.That(result, Is.SameAs(builder));
24+
}
25+
26+
[Test]
27+
public void UseReactiveUIWithDIContainer_Generic_Returns_Builder()
28+
{
29+
var builder = AppBuilder.Configure<Application>();
30+
var result = AppBuilderExtensions.UseReactiveUIWithDIContainer(
31+
builder,
32+
containerFactory: () => new Container(),
33+
containerConfig: _ => { },
34+
dependencyResolverFactory: c => new DryIocDependencyResolver(c));
35+
36+
Assert.That(result, Is.SameAs(builder));
37+
}
38+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using Avalonia;
2+
using DryIoc;
3+
using NUnit.Framework;
4+
using ReactiveUI.Avalonia.Splat;
5+
using Splat.DryIoc;
6+
7+
namespace ReactiveUI.Avalonia.DryIoc.Tests;
8+
9+
public class AvaloniaMixinsDryIocTests
10+
{
11+
[Test]
12+
public void UseReactiveUIWithDryIoc_ThrowsOnNullBuilder()
13+
{
14+
AppBuilder? builder = null;
15+
Assert.Throws<ArgumentNullException>(() =>
16+
AvaloniaMixins.UseReactiveUIWithDryIoc(builder!, _ => { }));
17+
}
18+
19+
[Test]
20+
public void UseReactiveUIWithDryIoc_ReturnsBuilder_NoThrow()
21+
{
22+
var builder = AppBuilder.Configure<Application>();
23+
var result = builder.UseReactiveUIWithDryIoc(_ => { });
24+
Assert.That(result, Is.SameAs(builder));
25+
}
26+
27+
[Test]
28+
public void UseReactiveUIWithDIContainer_ThrowsOnNullBuilder()
29+
{
30+
AppBuilder? builder = null;
31+
Assert.Throws<ArgumentNullException>(() =>
32+
AppBuilderExtensions.UseReactiveUIWithDIContainer(
33+
builder!,
34+
() => new Container(),
35+
_ => { },
36+
c => new DryIocDependencyResolver(c)));
37+
}
38+
39+
[Test]
40+
public void UseReactiveUIWithDIContainer_ReturnsBuilder_NoThrow()
41+
{
42+
var builder = AppBuilder.Configure<Application>();
43+
var container = new Container();
44+
45+
var result = builder.UseReactiveUIWithDIContainer(
46+
containerFactory: () => container,
47+
containerConfig: _ => { },
48+
dependencyResolverFactory: c => new DryIocDependencyResolver(c));
49+
50+
Assert.That(result, Is.SameAs(builder));
51+
}
52+
53+
[Test]
54+
public void DryIocDependencyResolver_Register_And_Resolve_WithAndWithoutContract()
55+
{
56+
var container = new Container();
57+
var resolver = new DryIocDependencyResolver(container);
58+
59+
resolver.Register(() => "a", typeof(string));
60+
resolver.Register(() => "b", typeof(string), "x");
61+
62+
var last = resolver.GetService(typeof(string));
63+
Assert.That(last, Is.EqualTo("b"));
64+
65+
var all = resolver.GetServices(typeof(string)).ToArray();
66+
Assert.That(all, Does.Contain("a"));
67+
Assert.That(all, Does.Contain("b"));
68+
}
69+
}

0 commit comments

Comments
 (0)