C# 如何防止继承财产和子财产在域/目的方面发生干涉?

C# 如何防止继承财产和子财产在域/目的方面发生干涉?,c#,oop,C#,Oop,我正在使用C#.Net 4.7.2 情况: 假设我们有两个域: 在一个例子中,我们需要询问特定类型:project.Tasks。因为打电话的人不需要知道 该项目有子项目:IsScheduleAbe[]: 在另一个领域,我们需要知道事件的层次结构树来安排它们 现在,在这种设计中,当我想将任务添加到project.Tasks时,我必须将任务添加为可调度到project.Children。我们携带冗余信息,有点像 我尝试过的另一种方法是覆盖项目中孩子的getter: public override

我正在使用C#.Net 4.7.2

情况:

假设我们有两个域: 在一个例子中,我们需要询问特定类型:project.Tasks。因为打电话的人不需要知道 该项目有子项目:IsScheduleAbe[]:

在另一个领域,我们需要知道事件的层次结构树来安排它们

现在,在这种设计中,当我想将任务添加到project.Tasks时,我必须将任务添加为可调度到project.Children。我们携带冗余信息,有点像

我尝试过的另一种方法是覆盖项目中孩子的getter:

public override List<ISchedulable> Children
{
    get => Tasks.Cast<ISchedulable>().ToList();
}
公共覆盖列表子项
{
get=>Tasks.Cast().ToList();
}
但这意味着,我总是投下整个名单!我不能迭代列表,因为它在每次迭代时都会被“修改”

第三种方法是,我在需要的时候构建层次结构。我知道所有类型都继承自IsSchedulable,因此我可以构建层次结构并设置父级和子级。但是,在我们计算父/子对象之前,该对象的父/子对象将再次为null


我错过了什么?是否有人有一个将域分开的设计想法?

Eric Evans在他的杰作《域驱动设计:软件的核心》中建议在一个域中绘制有界上下文。我想说的是,如果您已经知道一个概念(在本例中是可调度的、项目、任务和ToDo)用于不同的目的,那么您可能需要复制它们

无论如何,我似乎明白,一个项目不能有TODO或项目作为子项,一个任务不能有项目或TODO作为子项,TODO根本不能有子项。 让我们来看看这种方法,在这里我使用了复合模式和访问者模式:

public interface ISchedulable {
    ISchedulable Parent {get;set;}
    IEnumerable<ISchedulable> Children {get;} //this collection is readonly
    DateTime Start {get; set; }
    DateTime End {get; set; }
    T AcceptVisitor<T>(ISchedulableVisitor<T> visitor);
}
public interface ISchedulableVisitor<T> {
    T Visit(Project p);
    T Visit(Task t);
    T Visit(ToDo td);
}
public abstract class SchedulableBase : ISchedulable {
    public ISchedulable Parent {get;set;}
    public abstract IEnumerable<ISchedulable> Children {get;} //this collection is readonly
    public DateTime Start {get; set; }
    public DateTime End {get; set; }
    public abstract T AcceptVisitor<T>(ISchedulableVisitor<T> visitor);
}    

public class Project : SchedulableBase {
    public override IEnumerable<ISchedulable> Children => Tasks.Cast<ISchedulable>();
    private readonly List<Task> _tasks = new List<Task>();
    public IEnumerable<Task> Tasks => _tasks;
    public void AddTask(Task t) {
       t.Parent = this;
       _tasks.Add(t);
    } 
    public string Description {get;set;}
    public override T AcceptVisitor<T>(ISchedulableVisitor<T> visitor) => visitor.Visit(this);
}    

public class Task : SchedulableBase {
    public override IEnumerable<ISchedulable> Children => ToDos.Cast<ISchedulable>(); 
    private readonly List<ToDo> _todos = new List<ToDo>();
    public IEnumerable<ToDo> ToDos => _todos;
    public void AddToDo(ToDo t) {
       t.Parent = this;
       _todos.Add(t);
    }

    public Employee Head {get;set;}
    public override T AcceptVisitor<T>(ISchedulableVisitor<T> visitor) => visitor.Visit(this);
}

public class ToDo : SchedulableBase {
    public override IEnumerable<ISchedulable> Children => Enumerable.Empty<ISchedulable>();
    public object Whatever {get;set;}
    public override T AcceptVisitor<T>(ISchedulableVisitor<T> visitor) => visitor.Visit(this);
}

你没有一个基类继承了子类吗?因此,您可以在继承类的基类和层次结构树中放入最少的信息。@jdweng:基类为谁?继承类(子类)的属性多于基类(父类)。因此,您希望父对象拥有有限数量的属性,而子对象拥有详细的属性。感谢您为编写代码所做的努力。我喜欢复合模式的想法,我现在正在实施。直到现在我还没有弄坏什么东西,所以看起来不错=)
public class ToDosCounter : ISchedulableVisitor<int> {
     public int Visit(Project p) {
         int ris = 0;
         foreach (Task t in p.Tasks) {
              ris += t.AcceptVisitor(this);
         }
         return ris;
      }
      public int Visit(Task t) {
         int ris = 0;
         foreach(ToDo td in t.ToDos) {
              ris+=td.AcceptVisitor(this);
         }
         return ris;
      }
      public int Visit(ToDo td) {
         return 1;
      }
 }
      public void DoLogic(ISchedulable s) {
           var numberOfTodos = s.AcceptVisitor(new ToDoCounter());
           ///
      }