C#初心者を卒業しよう(第3回の解答例)
プログラム
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddTransient<DistanceService>()
.AddScoped<ToYards>()
.AddScoped<IDistance, ToYards>()
.AddScoped<ToMeters>()
.AddScoped<IDistance, ToMeters>()
.AddScoped<MetersToFeet>()
.AddScoped<IDistance, MetersToFeet>()
.AddScoped<FeetToMeters>()
.AddScoped<IDistance, FeetToMeters>();
using IHost host = builder.Build();
var service = host.Services.GetService<DistanceService>() ??
throw new NotImplementedException(
"Faild to create 'DistanceService' object.");
service.Run();
public interface IDistance
{
void Calculate(double distance);
string CreateAnswerMessage();
}
public class DistanceService(IServiceProvider serviceProvider)
{
public void Run()
{
var convertNumber = InputConvertNumber();
var distanceObject = Create(convertNumber) ??
throw new NotImplementedException(
"Faild to create 'IDistance' object.");
var distance = InputDistance();
distanceObject.Calculate(distance);
OutputAnswer(distanceObject);
}
protected virtual int InputConvertNumber()
{
Console.WriteLine("Please input convert number.");
Console.WriteLine("1 : Convert meters to yards.");
Console.WriteLine("2 : Convert yards to meters.");
Console.WriteLine("3 : Convert meters to feet.");
Console.WriteLine("4 : Convert feet to meters.");
if (int.TryParse(Console.ReadLine(), out var convertNumber))
{
return convertNumber;
}
throw new FormatException("Invalid input convert number.");
}
protected virtual IDistance? Create(int convertNumber)
{
switch (convertNumber)
{
case 1:
return (IDistance?)serviceProvider
.GetService(typeof(ToYards));
case 2:
return (IDistance?)serviceProvider
.GetService(typeof(ToMeters));
case 3:
return (IDistance?)serviceProvider
.GetService(typeof(MetersToFeet));
case 4:
return (IDistance?)serviceProvider
.GetService(typeof(FeetToMeters));
default:
throw new ArgumentOutOfRangeException(
$"{convertNumber} is out of range.");
}
}
protected virtual double InputDistance()
{
Console.WriteLine("Please input distance.");
if (double.TryParse(Console.ReadLine(), out var distance))
{
return distance;
}
throw new FormatException("Invalid input distance.");
}
protected virtual void OutputAnswer(IDistance distance)
{
var outputMessage = distance.CreateAnswerMessage();
Console.WriteLine(outputMessage);
}
}
public class ToYards : IDistance
{
private double _yards;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_yards = meters * 1.0936133d;
}
public string CreateAnswerMessage()
{
return $"{_meters} meters is {_yards} yards.";
}
}
public class ToMeters : IDistance
{
private double _yards;
private double _meters;
public void Calculate(double yards)
{
_yards = yards;
_meters = yards / 1.0936133d;
}
public string CreateAnswerMessage()
{
return $"{_yards} yards is {_meters} meters.";
}
}
public class MetersToFeet : IDistance
{
private double _feet;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_feet = meters / 0.3048d;
}
public string CreateAnswerMessage()
{
return $"{_meters} meters is {_feet} feet.";
}
}
public class FeetToMeters : IDistance
{
private double _feet;
private double _meters;
public void Calculate(double feet)
{
_feet = feet;
_meters = feet * 0.3048d;
}
public string CreateAnswerMessage()
{
return $"{_feet} feet is {_meters} meters.";
}
}
ダウンロード
解説
今回は前回と一部異なります。
入力メッセージを追加
ここは問題ありませんね。
Console.WriteLine("3 : Convert meters to feet.");
Console.WriteLine("4 : Convert feet to meters.");
オブジェクト生成を追加
オブジェクト生成部分を追加します。ここは少し違いますね。
public class DistanceFactory
{
public static IDistance Create(int convertNumber)
{
switch (convertNumber)
{
case 1:
return (IDistance?)serviceProvider
.GetService(typeof(ToYards));
case 2:
return (IDistance?)serviceProvider
.GetService(typeof(ToMeters));
case 3:
return (IDistance?)serviceProvider
.GetService(typeof(MetersToFeet));
case 4:
return (IDistance?)serviceProvider
.GetService(typeof(FeetToMeters));
default:
throw new ArgumentOutOfRangeException(
$"{convertNumber} is out of range.");
}
}
}
変換クラスを追加
メートルをフィートに変換するクラスを追加します。
public class MetersToFeet : IDistance
{
private double _feet;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_feet = meters / 0.3048;
}
public string CreateAnswerMessage()
{
return $"{_meters} meters is {_feet} feet.";
}
}
フィートをメートルに変換するクラスを追加します。
public class FeetToMeters : IDistance
{
private double _feet;
private double _meters;
public void Calculate(double feet)
{
_feet = feet;
_meters = feet * 0.3048;
}
public string CreateAnswerMessage()
{
return $"{_feet} feet is {_meters} meters.";
}
}
DI コンテナに登録
最後に DI コンテナに登録します。これを忘れないように。
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddTransient<DistanceService>()
.AddScoped<ToYards>()
.AddScoped<IDistance, ToYards>()
.AddScoped<ToMeters>()
.AddScoped<IDistance, ToMeters>()
.AddScoped<MetersToFeet>()
.AddScoped<IDistance, MetersToFeet>()
.AddScoped<FeetToMeters>()
.AddScoped<IDistance, FeetToMeters>();
using IHost host = builder.Build();
よろしければサポートをお願いします。 いただいたサポートは、書籍代、開発機器購入などに充てさせていただきます。