【发布时间】:2015-11-24 04:47:20
【问题描述】:
不确定标题是否准确代表我的问题,对此感到抱歉。
我有三个项目:持久性、核心(逻辑)和测试,设置如下(为简洁起见省略了一些内容):
持久性
public struct PatientData
{
public int? ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IPatientRepository : IDisposable
{
IEnumerable<PatientData> GetPatients();
PatientData GetPatientByID(int patientID);
void InsertPatient(PatientData patient);
void DeletePatient(int patientID);
void UpdatePatient(PatientData patient);
void Save();
}
class PatientRepositoryEF : IPatientRepository, IDisposable
{
// assume EF implementation here
}
public static class Factory
{
public static IPatientRepository GetPatientRepository() {
// not ideal, will refactor later
// assume EF for now
return new PatientRepositoryEF();
}
}
核心
public class Patient
{
// CTORS/DTORS
public Patient() {
this.repository = Persistence.Core.Factory.GetPatientRepository();
}
public Patient(Persistence.Core.IPatientRepository repository) {
// for testability, haven't actually used...
this.repository = repository;
}
~Patient() {
if (repository != null) {
repository.Dispose();
}
}
// PERSISTENCE
private Persistence.Core.IPatientRepository repository;
public void Fill(int patientID) {
Persistence.Core.PatientData data = repository.GetPatientByID(patientID);
this.ID = data.ID;
this.FirstName = data.FirstName;
this.LastName = data.LastName;
}
public void Save() {
repository.Save();
}
// other domain stuff
}
测试
static void Main(string[] args) {
Patient p = new Patient();
p.Fill(1546);
// test that data fills ok
}
这一切都很好,但我想转储公共 Fill 方法并设置一个公共构造函数来获取一个 ID,以便消费者可以 a)创建一个新的/空的 Patient,或者 b)通过 ctor 传递一个 ID 到相应地填充模型。 想象一下这些变化:
将新的 CTor 添加到 Core.Patient 并私有化 fill():
public Patient(int patientID) {
this.repository = Persistence.Core.Factory.GetPatientRepository();
fill(patientID);
}
void fill(int patientID) { /* fill method here */ }
把测试项目改成这样:
static void Main(string[] args) {
Patient p = new Patient(1546);
// test that data fills ok
}
现在,在测试项目之前完美运行的地方(p.Fill 暴露),如果没有对 Persistence 项目的引用,我无法再编译测试项目(您必须添加对程序集“Persistence”的引用)
这不是一个主要问题,我可以解决它,但我认为埋葬那个 Fill() 方法会很好。我猜这与构造对象时的依赖可见性有关,但另一方面,它可以很好地运行测试项目中的无参数构造函数,而测试项目不需要持久性引用。
我不清楚为什么需要此参考,唯一的变化是参数与无参数构造。有人可以解释吗?
编辑:确切的错误是:
“Persistence.Core.IPatientRepository”类型在未引用的程序集中定义。您必须添加对程序集“Persistence, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”的引用。
如果我用Patient p = new Patient() 替换Patient p = new Patient(1546);,一切都很好。
谢谢
【问题讨论】:
-
是
fill(int patientID)public void fill(int patientID)或无效fill(int patientID) -
是public的,我改成private从构造函数中调用,此时无法编译外层测试项目。
-
这只是对代码的评论,但我不得不将您指向Why are mutable structs "evil"? 以潜在地避免未来的头痛。
-
感谢 31eee384,我还没有完全决定在那里使用结构 - 我过去曾将它们用于 MVVM PropertyChanged 支持,它运行良好,但我没有看到这个讨论。也就是说,我以前被它们咬过,从那以后就变得小心了:)
-
至少对我而言,有几个“代码味道”:1) 患者有对其 PatientRepository 的引用。听起来很糟糕。 2)终结器中的代码,处理存储库引用。终结器将运行...当 GC 决定调用它时,(或者永远不会,如果您在该对象上调用
GC.SuppressFinalize)。即,您不知道它何时运行。听起来也很糟糕。 _repository.Dispose() 有什么作用?如果它“重要”,你应该控制它何时发生,如果不是......为什么在终结器中调用它?
标签: c# constructor repository-pattern