![見出し画像](https://assets.st-note.com/production/uploads/images/136507190/rectangle_large_type_2_abda36f180678c4582cb235d27f2d587.png?width=1200)
C#初心者を卒業しよう(第5回の解答例)
プログラム
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 enum ConvertNumber
{
ToYards = 1,
ToMeters = 2,
MetersToFeet = 3,
FeetToMeters = 4,
}
public class ConvertValues
{
public Type ConvertType { get; }
public string ConvertMessage { get; }
public ConvertValues(Type convertType, string convertMessage)
{
ConvertType = convertType;
ConvertMessage = convertMessage;
}
}
public class Const
{
public static readonly double METER_TO_YARD = 1.0936133d;
public static readonly double METER_TO_FOOT = 0.3048d;
public static readonly IReadOnlyDictionary<ConvertNumber, ConvertValues> CONVERT_VALUE_DIC =
new Dictionary<ConvertNumber, ConvertValues>
{
{
ConvertNumber.ToYards,
new ConvertValues(
typeof(ToYards),
$"{(int)ConvertNumber.ToYards} : Convert meters to yards.")
},
{
ConvertNumber.ToMeters,
new ConvertValues(
typeof(ToMeters),
$"{(int)ConvertNumber.ToMeters} : Convert yards to meters.")
},
{
ConvertNumber.MetersToFeet,
new ConvertValues(
typeof(MetersToFeet),
$"{(int)ConvertNumber.MetersToFeet} : Convert meters to feet.")
},
{
ConvertNumber.FeetToMeters,
new ConvertValues(
typeof(FeetToMeters),
$"{(int)ConvertNumber.FeetToMeters} : Convert feet to meters.")
},
};
}
public class DistanceService(IServiceProvider serviceProvider)
{
public void Run()
{
var convertNumber = InputConvertNumber();
var distanceObject = Create(
Const.CONVERT_VALUE_DIC[convertNumber].ConvertType) ??
throw new NotImplementedException(
"Faild to create 'IDistance' object.");
var distance = InputDistance();
distanceObject.Calculate(distance);
OutputAnswer(distanceObject);
}
protected virtual ConvertNumber InputConvertNumber()
{
Console.WriteLine("Please input convert number.");
foreach (var value in Const.CONVERT_VALUE_DIC.Values)
{
Console.WriteLine(value.ConvertMessage);
}
if (Enum.TryParse(
typeof(ConvertNumber),
Console.ReadLine(),
out var convertNumber))
{
if (Enum.IsDefined(typeof(ConvertNumber), convertNumber))
{
return (ConvertNumber)convertNumber;
}
throw new IndexOutOfRangeException(
$"Input is out of range. {(int)convertNumber}");
}
throw new FormatException("Invalid input convert number.");
}
protected virtual IDistance? Create(Type convertType) =>
(IDistance?)serviceProvider.GetService(convertType);
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 IDistance
{
void Calculate(double distance);
string CreateAnswerMessage();
}
public class ToMeters : IDistance
{
private double _yards;
private double _meters;
public void Calculate(double yards)
{
_yards = yards;
_meters = yards / Const.METER_TO_YARD;
}
public string CreateAnswerMessage()
{
return $"{_yards} yards is {_meters} meters.";
}
}
public class ToYards : IDistance
{
private double _yards;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_yards = meters * Const.METER_TO_YARD;
}
public string CreateAnswerMessage()
{
return $"{_meters} meters is {_yards} yards.";
}
}
public class MetersToFeet : IDistance
{
private double _feet;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_feet = meters / Const.METER_TO_FOOT;
}
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 * Const.METER_TO_FOOT;
}
public string CreateAnswerMessage()
{
return $"{_feet} feet is {_meters} meters.";
}
}
ダウンロード
解説
列挙(enum)に追加する。
public enum ConvertNumber
{
ToYards = 1,
ToMeters = 2,
MetersToFeet = 3,
FeetToMeters = 4,
}
定数と Dictionary を追加
public class Const
{
public static readonly double METER_TO_YARD = 1.0936133d;
public static readonly double METER_TO_FOOT = 0.3048d;
public static readonly IReadOnlyDictionary<ConvertNumber, ConvertValues> CONVERT_VALUE_DIC =
new Dictionary<ConvertNumber, ConvertValues>
{
{
ConvertNumber.ToYards,
new ConvertValues(
typeof(ToYards),
$"{(int)ConvertNumber.ToYards} : Convert meters to yards.")
},
{
ConvertNumber.ToMeters,
new ConvertValues(
typeof(ToMeters),
$"{(int)ConvertNumber.ToMeters} : Convert yards to meters.")
},
{
ConvertNumber.MetersToFeet,
new ConvertValues(
typeof(MetersToFeet),
$"{(int)ConvertNumber.MetersToFeet} : Convert meters to feet.")
},
{
ConvertNumber.FeetToMeters,
new ConvertValues(
typeof(FeetToMeters),
$"{(int)ConvertNumber.FeetToMeters} : Convert feet to meters.")
},
};
}
変換クラスを追加
メートルをフィートに変換するクラスを追加します。
public class MetersToFeet : IDistance
{
private double _feet;
private double _meters;
public void Calculate(double meters)
{
_meters = meters;
_feet = meters / Const.METER_TO_FOOT;
}
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 * Const.METER_TO_FOOT;
}
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>();
よろしければサポートをお願いします。 いただいたサポートは、書籍代、開発機器購入などに充てさせていただきます。