Skip to content

Commit

Permalink
Automatically register command settings
Browse files Browse the repository at this point in the history
Closes #428
  • Loading branch information
patriksvensson committed Feb 15, 2024
1 parent b6e0b23 commit 43228ea
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ public static void RegisterDependencies(this ITypeRegistrar registrar, CommandMo
throw new InvalidOperationException("Command setting type cannot be null.");
}

if (command.SettingsType is { IsAbstract: false, IsClass: true })
{
// Register the settings type
registrar?.Register(command.SettingsType, command.SettingsType);
}

if (command.CommandType != null)
{
registrar?.Register(command.CommandType, command.CommandType);
Expand Down
2 changes: 1 addition & 1 deletion test/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup Label="Settings">
<LangVersion>10</LangVersion>
<LangVersion>12</LangVersion>
<IsPackable>false</IsPackable>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ItemGroup>
<PackageReference Include="IsExternalInit" Version="1.0.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Shouldly" Version="4.2.1" />
<PackageReference Include="Spectre.Verify.Extensions" Version="22.3.1" />
<PackageReference Include="Verify.Xunit" Version="23.2.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#nullable enable

using Microsoft.Extensions.DependencyInjection;

namespace Spectre.Console.Tests.Unit.Cli;

public sealed partial class CommandAppTests
{
public sealed partial class Injection
{
public sealed class Settings
{
public sealed class CustomInheritedCommand : Command<CustomInheritedCommandSettings>
{
private readonly SomeFakeDependency _dep;

public CustomInheritedCommand(SomeFakeDependency dep)
{
_dep = dep;
}

public override int Execute(CommandContext context, CustomInheritedCommandSettings settings)
{
return 0;
}
}

public sealed class SomeFakeDependency
{
}

public abstract class CustomBaseCommandSettings : CommandSettings
{
}

public sealed class CustomInheritedCommandSettings : CustomBaseCommandSettings
{
}

private sealed class CustomTypeRegistrar : ITypeRegistrar
{
private readonly IServiceCollection _services;

public CustomTypeRegistrar(IServiceCollection services)
{
_services = services;
}

public ITypeResolver Build()
{
return new CustomTypeResolver(_services.BuildServiceProvider());
}

public void Register(Type service, Type implementation)
{
_services.AddSingleton(service, implementation);
}

public void RegisterInstance(Type service, object implementation)
{
_services.AddSingleton(service, implementation);
}

public void RegisterLazy(Type service, Func<object> func)
{
_services.AddSingleton(service, provider => func());
}
}

public sealed class CustomTypeResolver : ITypeResolver
{
private readonly IServiceProvider _provider;

public CustomTypeResolver(IServiceProvider provider)
{
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}

public object? Resolve(Type? type)
{
ArgumentNullException.ThrowIfNull(type);
return _provider.GetRequiredService(type);
}
}

[Fact]
public void Should_Inject_Settings()
{
static CustomTypeRegistrar BootstrapServices()
{
var services = new ServiceCollection();
services.AddSingleton<SomeFakeDependency, SomeFakeDependency>();
return new CustomTypeRegistrar(services);
}

// Given
var app = new CommandAppTester(BootstrapServices());

app.Configure(config =>
{
config.PropagateExceptions();
config.AddBranch<CustomBaseCommandSettings>("foo", b =>
{
b.AddCommand<CustomInheritedCommand>("bar");
});
});

// When
var result = app.Run("foo", "bar");

// Then
result.ExitCode.ShouldBe(0);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ namespace Spectre.Console.Tests.Unit.Cli;

public sealed partial class CommandAppTests
{
public sealed class Injection
public sealed partial class Injection
{
public sealed class FakeDependency
{
}

public sealed class InjectSettings : CommandSettings
public abstract class BaseInjectSettings : CommandSettings
{
}

public sealed class InjectSettings : BaseInjectSettings
{
public FakeDependency Fake { get; set; }

Expand Down
4 changes: 2 additions & 2 deletions test/Spectre.Console.Cli.Tests/Unit/CommandAppTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ public void Can_Register_Default_Command_Settings_When_Configuring_Application()

// Then
registrar.Registrations.ContainsKey(typeof(DogSettings)).ShouldBeTrue();
registrar.Registrations[typeof(DogSettings)].Count.ShouldBe(1);
registrar.Registrations[typeof(DogSettings)].Count.ShouldBe(2);
registrar.Registrations[typeof(DogSettings)].ShouldContain(typeof(DogSettings));
}

Expand Down Expand Up @@ -587,7 +587,7 @@ public void Can_Register_Command_Settings_When_Configuring_Application()

// Then
registrar.Registrations.ContainsKey(typeof(DogSettings)).ShouldBeTrue();
registrar.Registrations[typeof(DogSettings)].Count.ShouldBe(1);
registrar.Registrations[typeof(DogSettings)].Count.ShouldBe(2);
registrar.Registrations[typeof(DogSettings)].ShouldContain(typeof(DogSettings));
registrar.Registrations.ContainsKey(typeof(MammalSettings)).ShouldBeTrue();
registrar.Registrations[typeof(MammalSettings)].Count.ShouldBe(1);
Expand Down

0 comments on commit 43228ea

Please sign in to comment.