【C#】CoconaでMicrosoft.Extensions.DependencyInjectionを用いてDIを行う方法 (original) (raw)
やり方
下準備
まずは雑にそれっぽいファイルを用意しました。
$ tree . ├── Command │ └── UserCommand.cs ├── DI │ └── ServiceConfigurator.cs ├── Domain │ └── IUserRepository.cs ├── Infrastructure │ └── UserRepository.cs ├── Program.cs ├── UseCase └── UserUseCase.cs
public interface IUserRepository { int Add(string name); }
public class UserRepository(ILogger logger) : IUserRepository { private readonly ILogger _logger = logger;
private readonly Dictionary<int, string> _users = new();
public int Add(string name)
{
var id = _users.Count + 1;
_users.Add(id, name);
_logger.LogDebug("Added {name} with id {id}", name, id);
return id;
}
}
public interface IUserUseCase { void AddPerson(string name); }
public class UserUseCase(IUserRepository userRepository, ILogger logger) : IUserUseCase { public void AddPerson(string name) { userRepository.Add(name); logger.LogDebug("Added {name}", name); } }
それぞれ以下の対応で依存性注入を行ってほしいとします。
ILogger
:ConsoleLogger
IUserRepository
:UserRepository
IUserUseCase
:UserUseCase
CoconaAppBuilderで設定を行う
public class ServiceConfigurator(CoconaAppBuilder builder) { public void Configure() {
builder.Logging.AddConsole();
builder.Services
.AddSingleton<IUserRepository, UserRepository>()
.AddSingleton<IUserUseCase, UserUseCase>();
}
}
Microsoft.Extensions.DependencyInjection
の詳細の使い方はここでは説明しませんが、CoconaAppBuilder.Services
(IServiceCollection
)からDIコンテナに設定を行います。
依存関係の挿入を使用する - .NET | Microsoft Learn
builder.Services.AddSingleton<ISomeClient, SomeClient>();
AddSingleton
AddTransient
AddScoped
CoconaAppBuilder.Logging
にAddConsole
やAddJsonConsole
などを利用することでILogger
でどのように出力するのか設定することができます。このあたりはMicrosoft.Extensions.Logging
を参照してください。
【C#】MS製のLoggingライブラリである「Microsoft.Extensions.Logging」の基礎的な使い方 - はなちるのマイノート
builder.Logging.AddConsole();
また出力するログレベルの設定もできたりします。
builder.Logging.SetMinimumLevel(LogLevel.Debug);
コンストラクタに渡す値を設定したい場合は、引数にラムダ式を渡します。IServiceProvider
を用いるとDIコンテナに登録されているインスタンスを取得することができます。
builder.Services .AddSingleton(sp => new UserRepository(sp.GetRequiredService<ILogger>()));
コマンド作成
CoconaApp.AddCommand
によるコマンド登録ですが、[FromService]
を付与しなくても自動でCoconaが渡してくれます。少し古い? class-based styleのときは[FromService]
が必要だったのですが、今はいらないようです。まあ分かりづらいのであっても悪くはない気もしますが。
public class UserCommand(CoconaApp app) { public void AddCommand() {
app.AddCommand("add",(string name, IUserUseCase userUseCase, ILogger<UserCommand> logger) =>
{
userUseCase.AddPerson(name);
logger.LogInformation("Added: " + name);
});
}
}
エントリポイント作成
一応今回は細かくファイルを分けたので、それらを呼び出してあげます。
var builder = CoconaApp.CreateBuilder();
new ServiceConfigurator(builder).Configure();
var app = builder.Build();
new UserCommand(app).AddCommand();
app.Run();
あとがき
CoconaはMicrosoft.Extensions.DependencyInjection
+ Microsoft.Extensions.Logging
+ Microsoft.Extensions.Hosting
がデフォルトで入っています。
github.com
それぞれ多少学習コストはあるものの、使ってみるとかなり便利なので是非有効活用してみてください。
またそれらMicrosoft.Extensions.*
を入れないCocona.Lite
も一応用意されています。
www.nuget.org