Так что я действительно хочу, это несколько полезное дополнение вкладки в модуле PS. Кажется, что ValidateSet - путь сюда.
К сожалению, мои данные динамичны, поэтому я не могу аннотировать параметр со всеми допустимыми значениями upfront. DynamicParameters/IDynamicParameters, по-видимому, являются решением этой проблемы.
Объединяя эти вещи (и уменьшая мой отказ до простого тестового примера), мы получаем:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Threading.Tasks;
namespace PSDummy
{
[Cmdlet(VerbsCommon.Get, "BookDetails")]
public class GetBookDetails : Cmdlet, IDynamicParameters
{
IDictionary<string, string[]> m_dummyData = new Dictionary<string, string[]> {
{"Terry Pratchett", new [] {"Small Gods", "Mort", "Eric"}},
{"Douglas Adams", new [] {"Hitchhiker Guide", "The Meaning of Liff"}}
};
private RuntimeDefinedParameter m_authorParameter;
private RuntimeDefinedParameter m_bookParameter;
protected override void ProcessRecord()
{
// Do stuff here..
}
public object GetDynamicParameters()
{
var parameters = new RuntimeDefinedParameterDictionary();
m_authorParameter = CreateAuthorParameter();
m_bookParameter = CreateBookParameter();
parameters.Add(m_authorParameter.Name, m_authorParameter);
parameters.Add(m_bookParameter.Name, m_bookParameter);
return parameters;
}
private RuntimeDefinedParameter CreateAuthorParameter()
{
var p = new RuntimeDefinedParameter(
"Author",
typeof(string),
new Collection<Attribute>
{
new ParameterAttribute {
ParameterSetName = "BookStuff",
Position = 0,
Mandatory = true
},
new ValidateSetAttribute(m_dummyData.Keys.ToArray()),
new ValidateNotNullOrEmptyAttribute()
});
// Actually this is always mandatory, but sometimes I can fall back to a default
// value. How? p.Value = mydefault?
return p;
}
private RuntimeDefinedParameter CreateBookParameter()
{
// How to define a ValidateSet based on the parameter value for
// author?
var p = new RuntimeDefinedParameter(
"Book",
typeof(string),
new Collection<Attribute>
{
new ParameterAttribute {
ParameterSetName = "BookStuff",
Position = 1,
Mandatory = true
},
new ValidateSetAttribute(new string[1] { string.Empty }/* cannot fill this, because I cannot access the author */),
new ValidateNotNullOrEmptyAttribute()
});
return p;
}
}
}
К сожалению, этот крошечный фрагмент вызывает много проблем. Упорядочено по убыванию:
-
Я не вижу, как я могу создать соединение между параметрами. Если вы выберете автора, вы сможете выбрать только книгу, соответствующую автору. Пока
GetDynamicParameters()
всегда кажется апатридом: я не вижу возможности получить доступ к значению другого/более раннего динамического параметра. Пробовал держать его в поле, пробовал искатьMyInvocation
- не повезло. Возможно ли это? -
Как вы определяете значение по умолчанию для обязательного параметра? Не подходит этот глупый пример, но позвольте сказать, что вы можете хранить своего любимого автора. Отныне я хочу по умолчанию этого автора, но наличие указателя на автора по-прежнему является обязательным. Либо вы дали мне значение по умолчанию (и все еще можете указать что-то еще), либо вам нужно быть явным.
-
Завершение вкладок для строк с пробелами кажется странным/сломанным/ограниченным - потому что оно не заключает значение с кавычками (например, cmd.exe будет делать, например, если вы наберете
dir C:\Program <tab>
). Таким образом, завершение табуляции фактически прерывает вызов (если проблемы, описанные выше, будут разрешены,Get-BookDetails Ter<tab>
будет/будет расширяться доGet-BookDetails Terry Pratchett
, который помещает фамилию в позицию параметра 1 aka 'book'.
Не должно быть так сложно, конечно, кто-то уже сделал что-то подобное?
Обновление: после другого хорошего дня возиться и обманывать, я не вижу способа сделать эту работу. Командный элемент без апатии и будет повторяться снова и снова. В тот момент, когда я могу определить динамические параметры (GetDynamicParameters), я не могу получить доступ к их (текущим) значениям/видеть, к чему они привязаны - например. MyInvocation.BoundParameters равно нулю. Я оставлю вопрос открытым, но кажется, что это просто не поддерживается. Все примеры, которые я вижу, добавляют динамический параметр, основанный на значении статического, и это не имеет значения. Мудак.