//Methods //FIXME: should this be public? It is difficult to extend the behavior of the engine without //hosting the extension in the same assembly, unless we do this. internal ModelActions GetPossibleActions() { //Default - exclude: invalid, callbefore, callafter, calllast, which are handled seperatly. ModelActionFlags exclude = ModelActionFlags.CallBefore | ModelActionFlags.CallAfter | ModelActionFlags.CallLast; if (!this.InvalidActions) { exclude |= (ModelActionFlags)ModelItemFlags.Invalid; } //Loop through all models ModelActions totalactions = new ModelActions(); foreach (Model model in this.Models) { //Ignore disabled models if (model.Weight == 0 || model.Disabled) { continue; } totalactions.Add(model.Actions.FindFlag(exclude, false)); } //Delegate return(this.GetPossibleActions(totalactions)); }
protected ModelActions GetPossibleActions(ModelActions totalactions) { //Loop through all actions, specified ModelActions possibleactions = new ModelActions(); foreach (ModelAction action in totalactions) { //Ignore Disabled actions if (action.Weight == 0 || action.Disabled) { continue; } //Ignore CallLimit/CallOnce actions that have already been called (max times) if (action.Accessed >= action.CallLimit) { continue; } //Note: CallFirst and CallLast imply CallOnce if (action.Accessed > 0 && (action.CallFirst || action.CallLast)) { continue; } //Ignore Actions, that return Models when were over the limit of those models Type returntype = action.Method.ReturnType; if (!returntype.IsPrimitive && typeof(Model).IsAssignableFrom(returntype) && returntype != typeof(Model)) { Models found = (Models)this.Models.FindType(returntype).FindFlag((int)ModelItemFlags.Disabled, false); if (found.Count >= found.MaxInstances) { continue; } } //Determine if Requirements meet ModelRequirement failedrequirement = null; bool matched = MeetsRequirements(action.Requirements, out failedrequirement); if (matched) { //Requirements met, action can be called possibleactions.Add(action); } else { //Requirements not met, action can't be called //Unless the user wants this to be called, when the requirements aren't met if (this.InvalidActions && failedrequirement != null && failedrequirement.Throws) { //Note: We clone the action, and set the expected exception, just as if //it were an invalid action from the start. We also set the weight of the //invalid action, to the weight of the requirement, so it's not weighted //the same as the (positive) version that's specified at the action level ModelAction invalidaction = (ModelAction)action.Clone(); invalidaction.Exception = failedrequirement.Exception; invalidaction.ExceptionId = failedrequirement.ExceptionId; invalidaction.Weight = failedrequirement.Weight; possibleactions.Add(invalidaction); } } } possibleactions.SortByWeightDesc(); //Sort all actions, across models return(possibleactions); }