The first thing I noticed was the misuse of the factory bank account. factory, like you, should be used by the repository to create an instance based on data received from the data warehouse. Thus, your call to accountRepository.FindByID will return a FixedBankAccount or SavingsBankAccount object depending on the type of AccountType returned from the data store.
If interest applies only to instances of FixedBankAccount, you can perform a type check to make sure that you are working with the correct account type.
public void IssueLumpSumInterest(int accountId) { var account = _accountRepository.FindById(accountId) as FixedBankAccount; if (account == null) { throw new InvalidOperationException("Cannot add interest to Savings account."); } var ownerId = account.OwnerId; if (_accountRepository.Any(a => (a.BankUser.UserId == ownerId) && (a.AccountId != accountId))) { throw new InvalidOperationException("Cannot add interest when user own multiple accounts."); } account.AddInterest();
NOTE. FindById should only accept an ID parameter, not a lambda / Func. You indicated by the name "FindById" how the search will be performed. The fact that the value of accountId is compared with the BankAccountId property is a detail of the implementation hidden in this method. Name the method "FindBy" if you want to use a generic approach that uses lambda.
I would also NOT put AddInterest in the IBankAccount interface if all implementations do not support this behavior. Consider the separate IInterestEarningBankAccount interface that the AddInterest method provides. I would also consider using this interface instead of FixedBankAccount in the code above to make the code more convenient for maintenance and expansion if you add another type of account in the future that supports this behavior.
source share