Это типичный укус для заводской шаблон. Вы знаете, что вам нужен экземпляр Purchase
, но вы не знаете точного подтипа. (См. http://www.dotnetperls.com/factory и здесь для немного более сложного и полезного примера: http://msdn.microsoft.com/en-us/library/orm-9780596527730-01-05.aspx)
Ofc. это не исключает логику, которую вы уже реализовали, она просто помогает вам не повторять себя снова и снова, и логика завершается на одной фабрике, которую вы можете использовать в любом месте в любое время.
Взятые из вашего примера, простой завод может выглядеть следующим образом:
static class PurchaseFactory
{
public Static Purchase BuildPurchase(String[] parameters){
string productName = parameters[0];
decimal cost = decimal.Parse(parameters[1]);
int productCount = int.Parse(parameters[2]);
if (parameters.Length < 4)
{
return new Purchase(productName, cost, productCount);
}
else
{
decimal discount = decimal.Parse(parameters[3]);
return new FixedDiscountPurchase(productName, cost, productCount, discount);
}
}
}
Так, из любой точки в пределах вас кода, вам просто необходимо, чтобы:
string[] parameters = csvString.Split(';');
Purchase p = PurchaseFactory.BuildPurchase(parameters);
//p is now either "Purchase" or "FixedDiscountPurchase"
Ну, если речь идет только об этих двух классах, а желает узнать, была ли уценена цена или нет (и вычислить окончательную цену) - вы могли бы уйти с одного Purchase
класса, который содержит дисконтированный флаг и метод, чтобы получить FinalPrice в любом случае:
public class Purchase
{
public Decimal Discount { get; set; }
public Boolean Discounted { get; set; }
public String Name { get; set; }
public Decimal Price { get; set; }
public Int32 Count { get; set; }
public Decimal FinalPrice
{
get
{
if (!Discounted)
return Price;
else
return Price - Discount;
}
}
public Purchase (String csvString){
string[] parameters = csvString.Split(';');
Name = parameters[0];
Price = decimal.Parse(parameters[1]);
Count = int.Parse(parameters[2]);
if (parameters.Length == 4)
{
Discount = decimal.Parse(parameters[3]);
Discounted = true;
}
}
}
использование:
Purchase p = new Purchase(stringInput);
MessageBox.Show(p.FinalPrice.ToString());
Просто убедитесь, что обратиться к purchase.FinalPrice
, то вы не должны принимать забота о том, действительно ли цена дисконтирована или нет.
Вы пробовали идею отражения? –
Я не могу получить конструктор класса, тип которого я не знаю. Проблема заключается в том, как определить, какой из конструкторов классов вызывать. – Konstantin
Спасибо всем за ваши ответы. Это было очень информативно для меня. Теперь, я думаю, самый разумный способ - изготовление фабрики. Но идея о методе расширения тоже хороша. – Konstantin