I'm new to DDD and IOC/DI and I'm having some trouble figuring out how to design an entity that needs to use a state pattern to manage its status. As the transitions are somewhat complicated, I'm using a finite state machine (FSM) to handle the states (I'm using Stateless).
To further complicate the situation, the FSM needs to be loosely coupled to an entity. I.e. while I know that the state of the entity must be handled by a FSM, I don't necessarily know exactly what the FSM is (i.e. the entity doesn't know what states/triggers/transitions it might go through). The users use the term workflow to define the FSM (state, triggers, transitions, rules etc). The workflow changes independently of the entity. They might want to add new states, change rules, triggers etc. independent of any changes to the entity.
I'm handling this by dynamically loading an assembly that contains a definition of the FSM (which implements a known interface), then using a service that is injected into the entity, the entity calls the service and gets the FSM it is using. This involves potentially loading assemblies, caching the factory that creates the FSM and then assigning the FSM that is in the appropriate state to the entity. Finally, the FSM can return the set of valid triggers that can be provided to the UI so one of the those triggers can be selected and fired. The actual workflow in completely encapsulated externally to the entity.
So, currently I'm my entity looks something like this:
public class EntityUsingWorkflow
{
private readonly workflowService;
public Order(IWorkflowService service, string workflowKey, string status)
{
this.workflowService = service;
this.WorkflowKey = workflowKey;
this.Status = status;
// Note that the two lambdas are used to retrieve
// and set the state on the entity.
this.Workflow = service.GetStateMachine(workflowKey, () => this.Status, stateValue => this.Status = statValue );
}
public string WorkflowKey { get; set; }
public IStateMachine Workflow { get; private set; }
public string Status { get; private set; }
}
I'm concerned with this design. My basic understanding is that domain entities should not have dependencies injected into them, yet here I am injecting one. I also understand that the entity needs to handle its own state, so I'm hesitant to move the workflow completely out of the entity. Other ideas I've had, like an init method, would just move the injection to method injection.
What would be a clean way to design an entity with these requirements? Is it OK to inject a dependency in this situation?