I decided to use an abstract class to create an object responsible for the selection of an annuity formula
#region CalculationFormula implementation
public abstract class CalculationFormulaBase
{
public abstract List<AnnuityPayment> Execute(AnnuityContext context);
}
public class CalculationFormulaDifferential : CalculationFormulaBase
{
public override List<AnnuityPayment> Execute(AnnuityContext context)
{
decimal refundPrincipal = (decimal)context.PrincipalAmount / context.LoanTerm;
double monthlyRate = (double)context.InterestRate / 12 / 100;
decimal loanBalance = context.PrincipalAmount;
List<AnnuityPayment> annuityPayments = new List<AnnuityPayment>(context.LoanTerm + 1);
for (int i = 0; i < context.LoanTerm; i++)
{
decimal refundInterest = loanBalance * Convert.ToDecimal(monthlyRate);
loanBalance = loanBalance - refundPrincipal;
annuityPayments.Add(new AnnuityPayment { Period = String.Format("{0:#}", i + 1), RefundPrincipal = refundPrincipal, RefundInterest = refundInterest, MonthlyPayment = refundPrincipal + refundInterest, LoanBalance = loanBalance });
}
return annuityPayments;
}
}
public class CalculationFormulaEqual : CalculationFormulaBase
{
public override List<AnnuityPayment> Execute(AnnuityContext context)
{
double monthlyRate = (double)context.InterestRate / 12 / 100;
double coefficient = monthlyRate / (1 - Math.Pow(1 + monthlyRate, -context.LoanTerm));
decimal refundAnnuity = (decimal)context.PrincipalAmount * Convert.ToDecimal(coefficient);
decimal loanBalance = context.PrincipalAmount;
List<AnnuityPayment> annuityPayments = new List<AnnuityPayment>(context.LoanTerm + 1);
for (int i = 0; i < context.LoanTerm; i++)
{
decimal refundInterest = loanBalance * Convert.ToDecimal(monthlyRate);
decimal refundPrincipal = refundAnnuity - refundInterest;
loanBalance = loanBalance - refundPrincipal;
annuityPayments.Add(new AnnuityPayment { Period = String.Format("{0:#}", i + 1), RefundPrincipal = refundPrincipal, RefundInterest = refundInterest, MonthlyPayment = refundPrincipal + refundInterest, LoanBalance = loanBalance });
}
return annuityPayments;
}
}
#endregion
In the class AnnuityContext I have created properties to get or set the formula for calculating the annuity payments
public class AnnuityContext : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private IList<AnnuityPayment> m_AnnuityPayments = new List<AnnuityPayment>();
public IEnumerable<AnnuityPayment> AnnuityPayments
{
get
{
return m_AnnuityPayments;
}
}
private CalculationFormulaBase m_CalculationFormula;
public CalculationFormulaBase CalculationFormula
{
get { return m_CalculationFormula; }
set
{
if (m_CalculationFormula != value)
{
m_CalculationFormula = value;
EmptyAnnuityPayments();
}
}
}
//...
}
In the same class, I created a function Calculation () which calls the correct formula for calculating and updating some controls on the page
internal void Calculation()
{
m_AnnuityPayments = CalculationFormula.Execute(this);
NotifyPropertyChanged("AnnuityPayments");
//...
}
When the page is initialized in Silverlight I set the defait formula for calculating annuity:
public MainPage()
{
InitializeComponent();
this.AnnuityData = new AnnuityContext { VehiclePrice = 500000, DownPaymentPercent = 20, LoanTerm = 36, InterestRate = 15, Summ = 600000, PeriodsCount = 60, RateString = "16" };
sliderPrincipalAmount.Value = 400000;
//this.AnnuityData.CalculationFormula = new CalculationFormulaDifferential();
this.AnnuityData.CalculationFormula = new CalculationFormulaEqual();
this.DataContext = this.AnnuityData;
buttonCalculation.Focus();
}
Internal types or members are accessible only within files in the same assembly
. Perhaps you are assuming that it is somehow equivalent to inner classes.