@@ -63,6 +63,16 @@ protected CliCommandBuilder()
6363 /// </summary>
6464 public bool ShortFormAutoGenerate { get ; protected set ; }
6565
66+ /// <summary>
67+ /// Gets the command builders that are nested/external children of this command builder.
68+ /// </summary>
69+ public IEnumerable < CliCommandBuilder > Children => GetChildren ( DefinitionType ) ;
70+
71+ /// <summary>
72+ /// Gets the command builders that are nested/external parents of this command builder.
73+ /// </summary>
74+ public IEnumerable < CliCommandBuilder > Parents => GetParents ( DefinitionType ) ;
75+
6676 /// <summary>
6777 /// Builds a <see cref="Command"/> instance, populated with sub-commands, options, arguments and settings.
6878 /// </summary>
@@ -89,11 +99,6 @@ public object Bind(ParseResult parseResult)
8999 return Binder ( pr ) ;
90100 } ) ;
91101 }
92-
93- /// <summary>
94- /// Gets the command builders that are nested/external children of this command builder.
95- /// </summary>
96- public IEnumerable < CliCommandBuilder > Children => GetChildren ( DefinitionType ) ;
97102
98103 /// <summary>
99104 /// Registers this command builder so that it can be found by the definition class,
@@ -110,10 +115,10 @@ public void Register()
110115
111116 #region Static
112117
113- private static readonly Dictionary < Type , CliCommandBuilder > RegisteredDefinitionTypes =
118+ private static readonly Dictionary < Type , CliCommandBuilder > RegisteredCommandBuilders =
114119 new Dictionary < Type , CliCommandBuilder > ( ) ;
115120
116- private static readonly Dictionary < Type , HashSet < CliCommandBuilder > > RegisteredParentDefinitionTypes =
121+ private static readonly Dictionary < Type , HashSet < CliCommandBuilder > > RegisteredChildCommandBuilders =
117122 new Dictionary < Type , HashSet < CliCommandBuilder > > ( ) ;
118123
119124 /// <summary>
@@ -135,7 +140,7 @@ public static void Register<TDefinition>(CliCommandBuilder commandBuilder)
135140 /// <param name="commandBuilder">A command builder which builds a <see cref="Command"/>.</param>
136141 public static void Register ( Type definitionType , CliCommandBuilder commandBuilder )
137142 {
138- RegisteredDefinitionTypes [ definitionType ] = commandBuilder ;
143+ RegisteredCommandBuilders [ definitionType ] = commandBuilder ;
139144 }
140145
141146 /// <summary>
@@ -157,7 +162,7 @@ public static CliCommandBuilder Get<TDefinition>()
157162 /// <returns>The registered <see cref="CliCommandBuilder" /> instance.</returns>
158163 public static CliCommandBuilder Get ( Type definitionType )
159164 {
160- if ( ! RegisteredDefinitionTypes . TryGetValue ( definitionType , out var commandBuilder ) )
165+ if ( ! RegisteredCommandBuilders . TryGetValue ( definitionType , out var commandBuilder ) )
161166 {
162167 if ( definitionType . GetCustomAttribute < CliCommandAttribute > ( ) == null )
163168 throw new Exception ( $ "The class '{ definitionType . Name } ' should have [CliCommand] attribute.") ;
@@ -194,10 +199,18 @@ public static void RegisterAsChild<TParentDefinition>(CliCommandBuilder childCom
194199 /// <param name="childCommandBuilder">The nested/external child command builder.</param>
195200 public static void RegisterAsChild ( Type parentDefinitionType , CliCommandBuilder childCommandBuilder )
196201 {
197- if ( ! RegisteredParentDefinitionTypes . TryGetValue ( parentDefinitionType , out var children ) )
198- RegisteredParentDefinitionTypes [ parentDefinitionType ] = children = new HashSet < CliCommandBuilder > ( ) ;
202+ if ( ! RegisteredChildCommandBuilders . TryGetValue ( parentDefinitionType , out var children ) )
203+ RegisteredChildCommandBuilders [ parentDefinitionType ] = children = new HashSet < CliCommandBuilder > ( ) ;
199204
200205 children . Add ( childCommandBuilder ) ;
206+
207+ /*
208+ if (childCommandBuilder.ParentDefinitionType != null)
209+ {
210+ if (RegisteredDefinitionTypes.TryGetValue(childCommandBuilder.ParentDefinitionType, out var parent))
211+ RegisteredParentDefinitionTypes[childCommandBuilder.DefinitionType] = parent;
212+ }
213+ */
201214 }
202215
203216 /// <summary>
@@ -220,12 +233,49 @@ public static IEnumerable<CliCommandBuilder> GetChildren<TParentDefinition>()
220233 public static IEnumerable < CliCommandBuilder > GetChildren ( Type parentDefinitionType )
221234 {
222235 if ( parentDefinitionType == null
223- || ! RegisteredParentDefinitionTypes . TryGetValue ( parentDefinitionType , out var children ) )
236+ || ! RegisteredChildCommandBuilders . TryGetValue ( parentDefinitionType , out var children ) )
224237 return Enumerable . Empty < CliCommandBuilder > ( ) ;
225238
226239 return children ;
227240 }
228241
242+ /// <summary>
243+ /// Gets the command builders that are registered as nested/external parents of a child definition.
244+ /// </summary>
245+ /// <typeparam name="TDefinition">The child definition class.</typeparam>
246+ /// <returns>An enumerable whose elements are the <see cref="CliCommandBuilder" /> instances registered as nested/external parents.</returns>
247+ public static IEnumerable < CliCommandBuilder > GetParents < TDefinition > ( )
248+ {
249+ var definitionType = typeof ( TDefinition ) ;
250+
251+ return GetParents ( definitionType ) ;
252+ }
253+
254+
255+ /// <summary>
256+ /// Gets the command builders that are registered as nested/external parents of a child definition.
257+ /// </summary>
258+ /// <param name="definitionType">The type of the child definition class.</param>
259+ /// <returns>An enumerable whose elements are the <see cref="CliCommandBuilder" /> instances registered as nested/external parents.</returns>
260+ public static IEnumerable < CliCommandBuilder > GetParents ( Type definitionType )
261+ {
262+ while ( definitionType != null )
263+ {
264+ if ( RegisteredCommandBuilders . TryGetValue ( definitionType , out var commandBuilder )
265+ && commandBuilder . ParentDefinitionType != null
266+ && RegisteredChildCommandBuilders . TryGetValue ( commandBuilder . ParentDefinitionType , out var children )
267+ && children . Contains ( commandBuilder )
268+ && RegisteredCommandBuilders . TryGetValue ( commandBuilder . ParentDefinitionType , out var parentCommandBuilder ) )
269+ {
270+ yield return parentCommandBuilder ;
271+
272+ definitionType = parentCommandBuilder . ParentDefinitionType ;
273+ }
274+ else
275+ yield break ;
276+ }
277+ }
278+
229279 /// <summary>
230280 /// Gets an argument parser method for an argument type, if it's a collection type.
231281 /// <para>
0 commit comments