@@ -40,19 +40,40 @@ public ArgumentCompleterAttribute(Type type)
4040 Type = type ;
4141 }
4242
43+ /// <summary>
44+ /// Initializes a new instance of the <see cref="ArgumentCompleterAttribute"/> class.
45+ /// This constructor is used by derived attributes implementing <see cref="IArgumentCompleterFactory"/>.
46+ /// </summary>
47+ protected ArgumentCompleterAttribute ( )
48+ {
49+ if ( this is not IArgumentCompleterFactory )
50+ {
51+ throw PSTraceSource . NewInvalidOperationException ( ) ;
52+ }
53+ }
54+
4355 /// <summary>
4456 /// This constructor is used primarily via PowerShell scripts.
4557 /// </summary>
4658 /// <param name="scriptBlock"></param>
4759 public ArgumentCompleterAttribute ( ScriptBlock scriptBlock )
4860 {
49- if ( scriptBlock == null )
61+ if ( scriptBlock is null )
5062 {
5163 throw PSTraceSource . NewArgumentNullException ( nameof ( scriptBlock ) ) ;
5264 }
5365
5466 ScriptBlock = scriptBlock ;
5567 }
68+
69+ internal IArgumentCompleter CreateArgumentCompleter ( )
70+ {
71+ return Type != null
72+ ? Activator . CreateInstance ( Type ) as IArgumentCompleter
73+ : this is IArgumentCompleterFactory factory
74+ ? factory . Create ( )
75+ : null ;
76+ }
5677 }
5778
5879 /// <summary>
@@ -85,6 +106,67 @@ IEnumerable<CompletionResult> CompleteArgument(
85106 }
86107#nullable restore
87108
109+ /// <summary>
110+ /// Creates a new argument completer.
111+ /// </summary>
112+ /// <para>
113+ /// If an attribute that derives from <see cref="ArgumentCompleterAttribute"/> implements this interface,
114+ /// it will be used to create the <see cref="IArgumentCompleter"/>, thus giving a way to parameterize a completer.
115+ /// The derived attribute can have properties or constructor arguments that are used when creating the completer.
116+ /// </para>
117+ /// <example>
118+ /// This example shows the intended usage of <see cref="IArgumentCompleterFactory"/> to pass arguments to an argument completer.
119+ /// <code>
120+ /// public class NumberCompleterAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory {
121+ /// private readonly int _from;
122+ /// private readonly int _to;
123+ ///
124+ /// public NumberCompleterAttribute(int from, int to){
125+ /// _from = from;
126+ /// _to = to;
127+ /// }
128+ ///
129+ /// // use the attribute parameters to create a parameterized completer
130+ /// IArgumentCompleter Create() => new NumberCompleter(_from, _to);
131+ /// }
132+ ///
133+ /// class NumberCompleter : IArgumentCompleter {
134+ /// private readonly int _from;
135+ /// private readonly int _to;
136+ ///
137+ /// public NumberCompleter(int from, int to){
138+ /// _from = from;
139+ /// _to = to;
140+ /// }
141+ ///
142+ /// IEnumerable{CompletionResult} CompleteArgument(string commandName, string parameterName, string wordToComplete,
143+ /// CommandAst commandAst, IDictionary fakeBoundParameters) {
144+ /// for(int i = _from; i < _to; i++) {
145+ /// yield return new CompletionResult(i.ToString());
146+ /// }
147+ /// }
148+ /// }
149+ /// </code>
150+ /// </example>
151+ public interface IArgumentCompleterFactory
152+ {
153+ /// <summary>
154+ /// Creates an instance of a class implementing the <see cref="IArgumentCompleter"/> interface.
155+ /// </summary>
156+ /// <returns>An IArgumentCompleter instance.</returns>
157+ IArgumentCompleter Create ( ) ;
158+ }
159+
160+ /// <summary>
161+ /// Base class for parameterized argument completer attributes.
162+ /// </summary>
163+ [ AttributeUsage ( AttributeTargets . Field | AttributeTargets . Property ) ]
164+ public abstract class ArgumentCompleterFactoryAttribute : ArgumentCompleterAttribute , IArgumentCompleterFactory
165+ {
166+ /// <inheritdoc />
167+ public abstract IArgumentCompleter Create ( ) ;
168+ }
169+
88170 /// <summary>
89171 /// </summary>
90172 [ Cmdlet ( VerbsLifecycle . Register , "ArgumentCompleter" , HelpUri = "https://go.microsoft.com/fwlink/?LinkId=528576" ) ]
0 commit comments