【发布时间】:2018-11-02 11:43:18
【问题描述】:
这可能是一个非常初学者的问题,但是我搜索了很多主题并没有真正找到相同的情况,尽管我确信这种情况一直在发生。
我的项目/计划将跟踪建筑项目图纸的更改,并在图纸更改时向人们发送通知。
会有很多建设项目(工地),每个项目中都会有很多图纸。每张图纸都会有几个修订版(当它们发生更改时,会创建一个新修订版)。
这是我的项目类
public class Project
{
private readonly List<Drawing> _drawings = new List<Drawing>(30);
private readonly List<Person> _autoRecepients = new List<Person>(30);
public int ID { get; private set; }
public string ProjectNumber { get; private set; }
public string Name { get; private set; }
public bool Archived { get; private set; }
public List<Person> AutoRecepients { get { return _autoRecepients; } }
public Project(int id, string projectNumber, string name)
{
if (id < 1) { id = -1; }
ID = id;
ProjectNumber = projectNumber;
Name = name;
}
public bool AddDrawing(Drawing drawing)
{
if (drawing == null) return false;
if (_drawings.Contains(drawing)) { return true; }
_drawings.Add(drawing);
return _drawings.Contains(drawing);
}
public void Archive()
{
Archived = true;
}
public bool DeleteDrawing(Drawing drawing)
{
return _drawings.Remove(drawing);
}
public IEnumerable<Drawing> ListDrawings()
{
return _drawings.AsReadOnly();
}
public override string ToString()
{
return string.Format("{0} {1}", ProjectNumber, Name);
}
}
这是我的绘画课
public class Drawing : IDrawing
{
private List<IRevision> _revisions = new List<IRevision>(5);
private List<IssueRecord> _issueRecords = new List<IssueRecord>(30);
private IRevision _currentRevision;
public int ID { get; private set; }
public string Name { get; private set; }
public string Description { get; set; }
public Project Project { get; private set; }
public IRevision CurrentRevision { get { return _currentRevision; } }
public Drawing(int id, string name, string description, Project project)
{
// To be implemented
}
/// <summary>
/// Automatically issue the current revision to all Auto Recepients
/// </summary>
public void AutoIssue(DateTime date)
{
AutoIssue(date, _currentRevision);
}
/// <summary>
/// Automatically issue a particular revision to all Auto Recepients
/// </summary>
public void AutoIssue(DateTime date, IRevision revision)
{
}
public void IssueTo(Person person, DateTime date, IRevision revision)
{
_issueRecords.Add(new IssueRecord(date, this, revision, person));
throw new NotImplementedException();
}
public void IssueTo(Person person, DateTime date)
{
IssueTo(person, date, _currentRevision);
}
public void IssueTo(IEnumerable<Person> people, DateTime date)
{
IssueTo(people, date, _currentRevision);
}
public void IssueTo(IEnumerable<Person> people, DateTime date, IRevision revision)
{
foreach (var person in people)
{
IssueTo(person, date, revision);
}
}
public void Rename(string name)
{
if (string.IsNullOrWhiteSpace(name)) { return; }
Name = name;
}
public void Revise(IRevision revision)
{
if (revision.Name == null ) return;
_revisions.Add(revision);
_currentRevision = revision;
}
public struct IssueRecord
{
public int ID { get; private set; }
public DateTime Date { get; private set; }
public IDrawing Drawing { get; private set; }
public IRevision Revision { get; private set; }
public Person Person { get; private set; }
public IssueRecord(int id, DateTime date, IDrawing drawing, IRevision revision, Person person)
{
if (id < 1) { id = -1; }
ID = id;
Date = date;
Drawing = drawing;
Revision = revision;
Person = person;
}
}
}
这是修订结构
public struct Revision : IRevision
{
public int ID { get; private set; }
public string Name { get; }
public DateTime Date { get; set; }
public IDrawing Drawing { get; }
public IDrawingFile DrawingFile { get; private set; }
public Revision(int id, string name, IDrawing drawing, DateTime date, IDrawingFile drawingFile)
{
if (name == null) { throw new ArgumentNullException("name", "Cannot create a revision with a null name"); }
if (drawing == null) { throw new ArgumentNullException("drawing", "Cannot create a revision with a null drawing"); }
if (id < 1) { id = -1; }
ID = id;
Name = name;
Drawing = drawing;
Date = date;
DrawingFile = drawingFile;
}
public Revision(string name, IDrawing drawing, DateTime date, IDrawingFile drawingFile)
: this(-1, name, drawing, date, drawingFile)
{
}
public Revision(string name, IDrawing drawing)
: this(-1, name, drawing, DateTime.Today, null)
{
}
public void ChangeID(int id)
{
if (id < 1) { id = -1; }
ID = id;
}
public void SetDrawingFile(IDrawingFile drawingFile)
{
DrawingFile = drawingFile;
}
}
我的问题是与绘图类中的项目参考和修订结构中的绘图参考有关。 好像有点代码味道? 它似乎也可能在未来导致序列化问题。 有没有更好的方法来做到这一点?
绘图对象似乎有必要知道它属于哪个项目,这样如果我正在处理单个绘图对象,我就可以知道它们属于哪个项目。
同样,每个修订版本质上都是由图纸“拥有”或属于图纸的一部分。没有图纸,修订就没有意义,所以它需要参考它所属的图纸?
任何建议将不胜感激。
【问题讨论】:
-
循环引用非常常见,例如在 EF Code First 中。这就是设置外键的方式。继续前进,如果您发现异常或错误发生并卡住 - 我们可以提供帮助
-
这可能更适合在software engineering上提问
-
为什么需要在
Drawing中引用Project?并在Revision中引用Drawing?这些字段是否曾经使用过? -
@Spotted 我猜会涉及到对象关系映射,这些映射将用作外键作为导航属性。如果不是,那么就像您提到的那样,这些看起来有点多余。
-
主要的气味是你正在创建你的类之间的相互依赖关系,这会使测试变得更加困难。您可能想为 DeleteDrawing 编写一个测试,但读取签名的方式会强制这样的测试创建一个真实的 Drawing 对象。这样做可能需要您创建 15 项其他内容,然后设置各种属性,然后才能将其删除。通过使用接口来避免这种情况。然后你可以使用像 Moq 这样的东西来真正简化这些测试用例。
标签: c# oop circular-reference