private IEnumerable <Type> PrepareComposerTypes() { // create a list, remove those that cannot be enabled due to runtime level var composerTypeList = _composerTypes .Where(x => { // use the min/max levels specified by the attribute if any // otherwise, min: user composers are Run, anything else is Unknown (always run) // max: everything is Run (always run) var attr = x.GetCustomAttribute <RuntimeLevelAttribute>(); var minLevel = attr?.MinLevel ?? (x.Implements <IUserComposer>() ? RuntimeLevel.Run : RuntimeLevel.Unknown); var maxLevel = attr?.MaxLevel ?? RuntimeLevel.Run; return(_composition.RuntimeState.Level >= minLevel && _composition.RuntimeState.Level <= maxLevel); }) .ToList(); // enable or disable composers EnableDisableComposers(composerTypeList); // sort the composers according to their dependencies var requirements = new Dictionary <Type, List <Type> >(); foreach (var type in composerTypeList) { requirements[type] = null; } foreach (var type in composerTypeList) { GatherRequirementsFromRequireAttribute(type, composerTypeList, requirements); GatherRequirementsFromRequiredByAttribute(type, composerTypeList, requirements); } // only for debugging, this is verbose //_logger.Debug<Composers>(GetComposersReport(requirements)); // sort composers var graph = new TopoGraph <Type, KeyValuePair <Type, List <Type> > >(kvp => kvp.Key, kvp => kvp.Value); graph.AddItems(requirements); List <Type> sortedComposerTypes; try { sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).ToList(); } catch (Exception e) { // in case of an error, force-dump everything to log _logger.Info <Composers>("Composer Report:\r\n{ComposerReport}", GetComposersReport(requirements)); _logger.Error <Composers>(e, "Failed to sort composers."); throw; } // bit verbose but should help for troubleshooting //var text = "Ordered Composers: " + Environment.NewLine + string.Join(Environment.NewLine, sortedComposerTypes) + Environment.NewLine; _logger.Debug <Composers>("Ordered Composers: {SortedComposerTypes}", sortedComposerTypes); return(sortedComposerTypes); }
internal IEnumerable <Type> SortComposers(Dictionary <Type, List <Type> > requirements) { // sort composers var graph = new TopoGraph <Type, KeyValuePair <Type, List <Type> > >(kvp => kvp.Key, kvp => kvp.Value); graph.AddItems(requirements); List <Type> sortedComposerTypes; try { sortedComposerTypes = graph.GetSortedItems().Select(x => x.Key).Where(x => !x.IsInterface).ToList(); } catch (Exception e) { // in case of an error, force-dump everything to log _logger.LogInformation("Composer Report:\r\n{ComposerReport}", GetComposersReport(requirements)); _logger.LogError(e, "Failed to sort composers."); throw; } return(sortedComposerTypes); }