参数化构造函数需要引用项目
本文关键字:引用 项目 构造函数 参数 | 更新日期: 2023-09-27 18:23:56
不确定标题是否准确地代表了我的问题,很抱歉。
我有三个项目:持久性、核心(逻辑)和测试,设置如下(为了简洁起见,省略了一些内容):
持久性
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);
,一切都很好。
感谢
编辑:
this.repository = Persistence.Core.Factory.GetPatientRepository();
行似乎导致了您的错误。您意识到名称空间Persistence.Core
与您的项目Core
不一样,对吧?听起来你有一个名称空间和/或引用问题,你只需要系统地追踪它。很难远程计算出这一点。
所有项目依赖项必须链接一次,并且不能超过一次(否则会出现可怕的循环依赖项编译错误)。因此,在您的情况下,Core
项目必须具有对Persistence
的正式引用,然后Test
必须具有对Core
的正式引用(但不具有对Persistence
的正式引用)。如果Persistence
必须在Core
之外直接使用,那么您将需要通过Core
公开它,或者考虑重构您的设计。
对于那些试图创建典型的3层体系结构而没有完成真正隔离第1层和第3层的全部工作的人来说,循环依赖性问题可能会令人沮丧。两种可能有帮助的技术是事件处理程序/回调方法和具有更多接口的重构。这两种技术都倾向于需要进行实质性的重构,这会很快激励人们在开始按键之前在设计阶段进行长时间的思考。
设置2层体系结构并不总是很糟糕(取决于特定的上下文),但如果您采用这种方式,强烈建议您合并业务逻辑和数据层。与存储层相比,Presentation层几乎总是会经历更频繁、更彻底的更改,因此选择该层作为隔离层是有意义的。