Несмотря на то, что Workflow
и WorkflowStep
являются контейнерами данных, но сохранение их в стороне от иерархических мер не решит проблему разделения.
Логичнее сохранить WorkflowStep
в иерархии Workflow
и для того, чтобы справиться с развязкой, вы должны ввести IoC
в этом случае.
Прелесть IoC
в том, что изменение определений WorkflowStep
, являющегося списком в классе Workflow
, будетпросто прозрачно, когда вы будете рассматривать регистрацию типов в вашем контейнере IoC
.
Позвольте мне привести пример с Ninject
IoC
каркасом контейнера.
Определение интерфейсови соответственно реализуйте свои контейнеры данных:
public interface IWorkflow {
string UID { get; set; }
string parentID { get; set; }
IList<IWorkflowStep> Steps { get; set; }
}
public interface IWorkflowStep {
string UID { get; set; }
string parentID { get; set; }
}
public class Workflow : IWorkflow, Node {
public string UID { get; set; };
public string parentID { get; set; };
public IList<IWorkflowStep> Steps { get; set; }
}
public class WorkflowStep : IWorkflowStep, Node {
public string UID { get; set; };
public string parentID { get; set; };
}
И теперь модуль Ninject будет:
public class WorkflowModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
Bind<IWorkflow>().To<Workflow>();
Bind<IWorkflowStep>().To<WorkflowStep>();
Bind<IList>().To<List>();
}
#endregion
}
Это единственное место, где вы связываете свои интерфейсы с конкретными классами.А в остальном мире вы просто запрашиваете экземпляр определенного интерфейса.
Чтобы разрешить ваш тип, вам нужно создать Ninject Kernel
, который имеет тип IKernel
и конкретную реализацию * 1030.* загрузив определенный вами модуль .
Что-то вроде
var kernel = new StandardKernel(new WorkflowModule());
Теперь все, что вам нужно сделать, это определить нужный интерфейс, например:
IWorkflow workflow = kernel.Get<IWorkflow>();
IWorkflowStep workflowStep = kernel.Get<IWorkflowStep>();
Прелесть здесь в том, что вам не нужно беспокоиться о конкретной реализации, которая тесно связана с вашей системой.Именно интерфейс, с которым вы будете иметь дело, а остальное - забота вашей реализации контейнера IoC
.
Поскольку вас больше беспокоит то, что реализация WorkflowStep
должна быть изменена и не связана с Workflow
,Я думаю, это то, где IoC
начинает играть.
Обратите внимание, что вы можете использовать любой IoC
контейнерный фреймворк, такой как Unity , Spring.NET , StructureMap и т. Д. Я использовал Ninject, потому что мне это удобно.