Skip to content

Commit

Permalink
feat: Enable constructor injection (#1581)
Browse files Browse the repository at this point in the history
* feat: Enable constructor injection

* fix: CVE in System.Text.Json
  • Loading branch information
linkdotnet authored Oct 10, 2024
1 parent 8ff1bf3 commit dd25f77
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 14 deletions.
14 changes: 7 additions & 7 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<GlobalPackageReference Include="AsyncFixer" Version="1.6.0" PrivateAssets="All" IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"/>
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167" PrivateAssets="All" IncludeAssets="Runtime;Build;Native;contentFiles;Analyzers"/>
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageVersion Include="Meziantou.Polyfill" Version="1.0.39" />
<PackageVersion Include="Meziantou.Polyfill" Version="1.0.40" />
</ItemGroup>

<ItemGroup Label="Shared">
Expand Down Expand Up @@ -42,7 +42,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="3.2.1"/>

<!-- Due to a CVE in System.Text.Json we explicitly reference the latest version of System.Text.Json -->
<PackageVersion Include="System.Text.Json" Version="6.0.9"/>
<PackageVersion Include="System.Text.Json" Version="6.0.10"/>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
Expand All @@ -59,7 +59,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="5.0.17"/>

<!-- Due to a CVE in System.Text.Json we explicitly reference the latest version of System.Text.Json -->
<PackageVersion Include="System.Text.Json" Version="6.0.9"/>
<PackageVersion Include="System.Text.Json" Version="6.0.10"/>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
Expand All @@ -75,7 +75,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.33"/>

<!-- Due to a CVE in System.Text.Json we explicitly reference the latest version of System.Text.Json -->
<PackageVersion Include="System.Text.Json" Version="6.0.9"/>
<PackageVersion Include="System.Text.Json" Version="6.0.10"/>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net7.0'">
Expand All @@ -91,7 +91,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="7.0.20"/>

<!-- Due to a CVE in System.Text.Json we explicitly reference the latest version of System.Text.Json -->
<PackageVersion Include="System.Text.Json" Version="8.0.4"/>
<PackageVersion Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
Expand All @@ -107,7 +107,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="8.0.8"/>

<!-- Due to a CVE in System.Text.Json we explicitly reference the latest version of System.Text.Json -->
<PackageVersion Include="System.Text.Json" Version="8.0.4"/>
<PackageVersion Include="System.Text.Json" Version="8.0.5"/>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
Expand All @@ -122,7 +122,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.0-rc.1.24452.1"/>
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="9.0.0-rc.1.24452.1"/>

<PackageVersion Include="System.Text.Json" Version="8.0.4" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
</ItemGroup>

<ItemGroup Label="Test Dependencies">
Expand Down
18 changes: 13 additions & 5 deletions src/bunit.core/Rendering/BunitComponentActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ internal class BunitComponentActivator : IComponentActivator
private readonly ComponentFactoryCollection factories;
private readonly IComponentActivator componentActivator;

public BunitComponentActivator(ComponentFactoryCollection factories, IComponentActivator? externalComponentActivator)
public BunitComponentActivator(
IServiceProvider serviceProvider,
ComponentFactoryCollection factories,
IComponentActivator? externalComponentActivator)
{
this.factories = factories ?? throw new ArgumentNullException(nameof(factories));
this.componentActivator = externalComponentActivator ?? DefaultComponentActivator.Instance;
this.componentActivator = externalComponentActivator ?? new DefaultComponentActivator(serviceProvider);
}

public IComponent CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type componentType)
Expand Down Expand Up @@ -43,12 +46,17 @@ public IComponent CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessed

private sealed class DefaultComponentActivator : IComponentActivator
{
public static IComponentActivator Instance { get; } = new DefaultComponentActivator();
private readonly IServiceProvider serviceProvider;

public DefaultComponentActivator(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}

/// <inheritdoc />
public IComponent CreateInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] Type componentType)
{
return (IComponent)Activator.CreateInstance(componentType)!;
{
return (IComponent)ActivatorUtilities.CreateInstance(serviceProvider, componentType);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/bunit.core/Rendering/TestRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public TestRenderer(IRenderedComponentActivator renderedComponentActivator, Test
/// Initializes a new instance of the <see cref="TestRenderer"/> class.
/// </summary>
public TestRenderer(IRenderedComponentActivator renderedComponentActivator, TestServiceProvider services, ILoggerFactory loggerFactory)
: base(services, loggerFactory, new BunitComponentActivator(services.GetRequiredService<ComponentFactoryCollection>(), null))
: base(services, loggerFactory, new BunitComponentActivator(services, services.GetRequiredService<ComponentFactoryCollection>(), null))
{
logger = loggerFactory.CreateLogger<TestRenderer>();
this.activator = renderedComponentActivator;
Expand All @@ -89,7 +89,7 @@ public TestRenderer(IRenderedComponentActivator renderedComponentActivator, Test
/// Initializes a new instance of the <see cref="TestRenderer"/> class.
/// </summary>
public TestRenderer(IRenderedComponentActivator renderedComponentActivator, TestServiceProvider services, ILoggerFactory loggerFactory, IComponentActivator componentActivator)
: base(services, loggerFactory, new BunitComponentActivator(services.GetRequiredService<ComponentFactoryCollection>(), componentActivator))
: base(services, loggerFactory, new BunitComponentActivator(services, services.GetRequiredService<ComponentFactoryCollection>(), componentActivator))
{
logger = loggerFactory.CreateLogger<TestRenderer>();
this.activator = renderedComponentActivator;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.JSInterop;

namespace Bunit.TestAssets.SampleComponents;

public class ConstructorInjectionComponent : ComponentBase
{
public IJSRuntime JSRuntime { get; }

public ConstructorInjectionComponent(IJSRuntime jsRuntime)
{
JSRuntime = jsRuntime;
}
}
10 changes: 10 additions & 0 deletions tests/bunit.web.tests/Rendering/RenderedComponentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,14 @@ public void Test020()

Should.Throw<ComponentDisposedException>(() => target.Instance);
}
#if NET9_0_OR_GREATER

[Fact(DisplayName = "Component with constructor dependencies is resolved when rendered")]
public void Test021()
{
var cut = RenderComponent<ConstructorInjectionComponent>();

cut.Instance.JSRuntime.ShouldNotBeNull();
}
#endif
}

0 comments on commit dd25f77

Please sign in to comment.