
C#初心者を卒業しよう(第3回の解答例)
プログラム
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddTransient<DistanceService>()
.AddScoped<IToYards, ToYards>()
.AddScoped<IToMeters, ToMeters>()
.AddScoped<IMetersToFeet, MetersToFeet>()
.AddScoped<IFeetToMeters, 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(IToYards));
case 2:
return (IDistance?)serviceProvider.GetService(typeof(IToMeters));
case 3:
return (IDistance?)serviceProvider.GetService(typeof(IMetersToFeet));
case 4:
return (IDistance?)serviceProvider.GetService(typeof(IFeetToMeters));
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 interface IToYards : IDistance
{
}
public class ToYards : IToYards
{
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 interface IToMeters : IDistance
{
}
public class ToMeters : IToMeters
{
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 interface IMetersToFeet : IDistance
{
}
public class MetersToFeet : IMetersToFeet
{
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 interface IFeetToMeters : IDistance
{
}
public class FeetToMeters : IFeetToMeters
{
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(IToYards));
case 2:
return (IDistance?)serviceProvider
.GetService(typeof(IToMeters));
case 3:
return (IDistance?)serviceProvider
.GetService(typeof(IMetersToFeet));
case 4:
return (IDistance?)serviceProvider
.GetService(typeof(IFeetToMeters));
default:
throw new ArgumentOutOfRangeException(
$"{convertNumber} is out of range.");
}
}
}
変換クラスを追加
メートルをフィートに変換するインターフェースとクラスを追加します。
public interface IMetersToFeet : IDistance
{
}
public class MetersToFeet : IMetersToFeet
{
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 interface IFeetToMeters : IDistance
{
}
public class FeetToMeters : IFeetToMeters
{
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<IToYards, ToYards>()
.AddScoped<IToMeters, ToMeters>()
.AddScoped<IMetersToFeet, MetersToFeet>()
.AddScoped<IFeetToMeters, FeetToMeters>();
using IHost host = builder.Build();
いいなと思ったら応援しよう!
