using System;
using System.Collections.Generic;
using System.Linq;
namespace TemplateMethodSample
{
class Program
{
static void Main(string[] args)
{
var standardOrder = new StandardOrder {
Number = 5, Text = "standard", StandardFee = 500,
Orders = new List<StandardOrderItem> {
new StandardOrderItem { Number = 8, Price = 300, Something = "something" },
new StandardOrderItem { Number = 4, Price = 10000, Something = "else" },
}
};
Console.WriteLine(new StandardOrderProcessor().Process(standardOrder));
var industryOrder = new IndustryOrder
{
Number = 100,
Text = "standard",
Prefix = "industry_",
Orders = new List<IndustryCompatibleOrderItem> {
new IndustryCompatibleOrderItem { Number = 9, OtherPrice = 53.23234m, SomethingElse = "something" },
new IndustryCompatibleOrderItem { Number = 5, OtherPrice = 42.3531532152m, SomethingElse = "else" },
}
};
Console.WriteLine(new IndustryOrderProcessor().Process(industryOrder));
Console.ReadLine();
}
}
abstract class OrderProcesorBase<TOrder, TItem>
where TOrder : OrderBase<TItem>
where TItem : OrderItemBase
{
public Result Process(TOrder order)
{
if (!this.Check(order))
return Result.Wrong;
int normalized = this.Normalize(order);
string s = order.Orders.Aggregate(string.Empty, (acc, x) => acc += this.Convert(order, x));
double total = order.Orders.Sum(x => GetPrice(order, x));
var result = BuildResult(s, total, normalized);
return result;
}
protected bool Check(TOrder order)
{
return order.Number > 0;
}
protected int Normalize(TOrder order)
{
return order.Number % 10000;
}
protected Result BuildResult(string fullDescription, double total, int normalizedNumber)
{
return new Result(normalizedNumber, fullDescription, total);
}
protected abstract string Convert(TOrder order, TItem orderItem);
protected abstract double GetPrice(TOrder order, TItem orderItem);
}
class Result
{
public Result(int number, string desc, double total = 0.0)
{
this.Number = number;
this.Description = desc;
this.Total = total;
}
public int Number { get; set; }
public string Description { get; set; }
public double Total { get; set; }
public static Result Wrong => new Result(-666, string.Empty);
public override string ToString()
{
return $"Number: {this.Number} Description: {this.Description} Total: {this.Total}";
}
}
class StandardOrderProcessor : OrderProcesorBase<StandardOrder, StandardOrderItem>
{
protected override string Convert(StandardOrder order, StandardOrderItem orderItem)
{
return orderItem.Something.ToUpper();
}
protected override double GetPrice(StandardOrder order, StandardOrderItem orderItem)
{
return order.StandardFee + orderItem.Price;
}
}
class IndustryOrderProcessor : OrderProcesorBase<IndustryOrder, IndustryCompatibleOrderItem>
{
protected override string Convert(IndustryOrder order, IndustryCompatibleOrderItem orderItem)
{
return order.Prefix + orderItem.SomethingElse;
}
protected override double GetPrice(IndustryOrder order, IndustryCompatibleOrderItem orderItem)
{
return (double)orderItem.OtherPrice;
}
}
abstract class OrderItemBase
{
public int Number { get; set; }
}
class OrderBase
{
public int Number { get; set; }
public string Text { get; set; }
}
class OrderBase<TItem> : OrderBase
where TItem : OrderItemBase
{
public List<TItem> Orders { get; set; }
}
class StandardOrder : OrderBase<StandardOrderItem>
{
public int StandardFee { get; set; }
}
class StandardOrderItem : OrderItemBase
{
public string Something { get; set; }
public int Price { get; set; }
}
class IndustryOrder : OrderBase<IndustryCompatibleOrderItem>
{
public string Prefix { get; set; }
}
class IndustryCompatibleOrderItem : OrderItemBase
{
public string SomethingElse { get; set; }
public decimal OtherPrice { get; set; }
}
}