BankAccount テーブルがあります。LINQ to SQL は、以下に示すように「BankAccount」という名前のクラスを生成します。
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")]
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged
今、初心者なので、自分でドメイン オブジェクトを新しく作成しています。IBankAccount インターフェイスと FixedBankAccount クラスを参照してください。重要なポイントは、ポリモーフィックな動作があることです。IBankAccount は、FixedBankAccount または SavingsBankAccount にすることができます。
この例の別の質問については、次の 2 つのコメントがあります。
- @mouters : 「リポジトリ オブジェクトとドメイン オブジェクトがあるのは奇妙です。リポジトリはドメイン オブジェクトを返すだけではいけませんか?」</li>
- @SonOfPirate : 「ファクトリは、データ ストアから取得したデータに基づいてインスタンスを作成するためにリポジトリで使用する必要があります。」</li>
質問
1) ドメイン エンティティを手動で作成しています。間違ったアプローチですか?それが間違っている場合、LINQ to SQL クラスはポリモーフィズムをどのように処理しますか? これらのクラスにメソッドを追加する方法は?
2) データ ストアから取得したデータに基づいてインスタンスを作成するために、リポジトリでファクトリをどのように使用する必要がありますか? コード例またはリファレンスはありますか?
3) 単一責任原則を満たすか?
コード
public interface IBankAccount
{
int BankAccountID { get; set; }
double Balance { get; set; }
string AccountStatus { get; set; }
void FreezeAccount();
void AddInterest();
}
public class FixedBankAccount : IBankAccount
{
public int BankAccountID { get; set; }
public string AccountStatus { get; set; }
public double Balance { get; set; }
public void FreezeAccount()
{
AccountStatus = "Frozen";
}
}
public class BankAccountService
{
RepositoryLayer.IRepository<RepositoryLayer.BankAccount> accountRepository;
ApplicationServiceForBank.IBankAccountFactory bankFactory;
public BankAccountService(RepositoryLayer.IRepository<RepositoryLayer.BankAccount> repo, IBankAccountFactory bankFact)
{
accountRepository = repo;
bankFactory = bankFact;
}
public void FreezeAllAccountsForUser(int userId)
{
IEnumerable<RepositoryLayer.BankAccount> accountsForUser = accountRepository.FindAll(p => p.BankUser.UserID == userId);
foreach (RepositoryLayer.BankAccount oneOfRepositoryAccounts in accountsForUser)
{
DomainObjectsForBank.IBankAccount domainBankAccountObj = bankFactory.CreateAccount(oneOfRepositoryAccounts);
if (domainBankAccountObj != null)
{
domainBankAccountObj.BankAccountID = oneOfRepositoryAccounts.BankAccountID;
domainBankAccountObj.FreezeAccount();
this.accountRepository.UpdateChangesByAttach(oneOfRepositoryAccounts);
oneOfRepositoryAccounts.Status = domainBankAccountObj.AccountStatus;
this.accountRepository.SubmitChanges();
}
}
}
}
public interface IBankAccountFactory
{
DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositoryAccount);
}
public class MySimpleBankAccountFactory : IBankAccountFactory
{
//Is it correct to accept repositry inside factory?
public DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositoryAccount)
{
DomainObjectsForBank.IBankAccount acc = null;
if (String.Equals(repositoryAccount.AccountType, "Fixed"))
{
acc = new DomainObjectsForBank.FixedBankAccount();
}
if (String.Equals(repositoryAccount.AccountType, "Savings"))
{
//acc = new DomainObjectsForBank.SavingsBankAccount();
}
return acc;
}
}
読書: