Какие быстрые интерфейсы Вы сделали или видели в C#, которые были очень ценны? Что было настолько большим о них?

Это будет совет / обходной путь

https://<<yourjenkinsdomain>>/job/<<yourjobname>>/configure (will open the configuration of your job)

Однако

https://<<yourjenkinsdomain>>/job/<<yourjobname>>/config.xml (will give the job configuration in an xml format)

Вы можете скачать этот xml через curl во время выполнения или с помощью jenkins cli и использовать grep с опцией -B найти описание по значению.

Учитывая, что вы скопировали с именем "config.xml"

cat config.xml | grep -B 1 "description"

Дадим вам описание и имя параметра сборки

 Grep command 
 -B NUM, --before-context=NUM
          Print  NUM  lines  of  leading  context  before  matching lines.
          Places  a  line  containing  a  group  separator  (--)   between
          contiguous  groups  of  matches.  With the -o or --only-matching
          option, this has no effect and a warning is given.

Пример вывода:

cat config.xml | grep -B 1 "description"

<actions/>
<description>Job description : Automation </description>
--
<name>branch</name>
<description>mandatory parameter , used for automation</description>

-

Альтернатива:

jenkins cli имеет опцию для установки значения

set-build-description   Sets the description of a build.
set-build-parameter Update/set the build parameter of the current build in progress. [deprecated]

, вы можете написать небольшой скрипт и получить значения в переменные и использовать их

18
задан Community 23 May 2017 в 10:29
поделиться

10 ответов

Престижность за проверку параметра метода, Вы дали мне новую идею для наших быстрых API. Я ненавидел наши проверки предварительного условия так или иначе...

Я создал систему расширяемости для нового продукта в разработке, где можно бегло описать доступные команды, элементы пользовательского интерфейса и т.д. Это работает сверху StructureMap и FluentNHibernate, которые являются хорошими API также.

MenuBarController mb;
// ...
mb.Add(Resources.FileMenu, x =>
{
  x.Executes(CommandNames.File);
  x.Menu
    .AddButton(Resources.FileNewCommandImage, Resources.FileNew, Resources.FileNewTip, y => y.Executes(CommandNames.FileNew))
    .AddButton(null, Resources.FileOpen, Resources.FileOpenTip, y => 
    {
      y.Executes(CommandNames.FileOpen);
      y.Menu
        .AddButton(Resources.FileOpenFileCommandImage, Resources.OpenFromFile, Resources.OpenFromFileTop, z => z.Executes(CommandNames.FileOpenFile))
        .AddButton(Resources.FileOpenRecordCommandImage, Resources.OpenRecord, Resources.OpenRecordTip, z => z.Executes(CommandNames.FileOpenRecord));
     })
     .AddSeperator()
     .AddButton(null, Resources.FileClose, Resources.FileCloseTip, y => y.Executes(CommandNames.FileClose))
     .AddSeperator();
     // ...
});

И можно настроить все команды, доступные как это:

Command(CommandNames.File)
  .Is<DummyCommand>()
  .AlwaysEnabled();

Command(CommandNames.FileNew)
  .Bind(Shortcut.CtrlN)
  .Is<FileNewCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileSave)
  .Bind(Shortcut.CtrlS)
  .Enable(WorkspaceStatusProviderNames.DocumentOpen)
  .Is<FileSaveCommand>();

Command(CommandNames.FileSaveAs)
  .Bind(Shortcut.CtrlShiftS)
  .Enable(WorkspaceStatusProviderNames.DocumentOpen)
  .Is<FileSaveAsCommand>();

Command(CommandNames.FileOpen)
  .Is<FileOpenCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileOpenFile)
  .Bind(Shortcut.CtrlO)
  .Is<FileOpenFileCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Command(CommandNames.FileOpenRecord)
  .Bind(Shortcut.CtrlShiftO)
  .Is<FileOpenRecordCommand>()
  .Enable(WorkspaceStatusProviderNames.DocumentFactoryRegistered);

Наше представление настраивает их средства управления для стандартных команд меню редактирования с помощью сервиса, данного им рабочей областью, где они просто говорят этому наблюдать их:

Workspace
  .Observe(control1)
  .Observe(control2)

Если пользовательские вкладки к средствам управления, рабочая область автоматически получает соответствующий адаптер для управления и обеспечивает операции буфера обмена и отмена/восстановление.

Это помогло нам уменьшить код установки существенно и делает это еще более читаемым.


Я забыл говорить о библиотеке, которой мы пользуемся в наших предъявителях модели WinForms MVP для проверки представлений: FluentValidation. Действительно легкий, действительно тестируемый, действительно хороший!

8
ответ дан 30 November 2019 в 07:09
поделиться

Это - на самом деле первый раз, когда я услышал термин "быстрый интерфейс". Но двумя примерами, которые приходят на ум, является LINQ и неизменные наборы.

Под покрытиями LINQ является рядом методов, большинство которых является дополнительными методами, которые берут по крайней мере один IEnumerable и возвращают другой IEnumerable. Это позволяет, чтобы очень мощный метод объединил в цепочку

var query = someCollection.Where(x => !x.IsBad).Select(x => x.Property1);

Неизменные типы и более конкретно наборы имеют очень похожий шаблон. Неизменные Наборы возвращают новый набор для того, что обычно было бы операцией видоизменения. Так создание набора часто превращается в серию цепочечных вызовов метода.

var array = ImmutableCollection<int>.Empty.Add(42).Add(13).Add(12);
9
ответ дан 30 November 2019 в 07:09
поделиться

Я люблю быстрый интерфейс в CuttingEdge. Условия.

От их образца:

 // Check all preconditions:
 id.Requires("id")
    .IsNotNull()          // throws ArgumentNullException on failure 
    .IsInRange(1, 999)    // ArgumentOutOfRangeException on failure 
    .IsNotEqualTo(128);   // throws ArgumentException on failure 
 

Я нашел, что это намного легче считать и делает меня намного более эффективным при проверке моих предварительных условий (и условия сообщения) в методах чем тогда, когда я имею 50 если операторы для обработки тех же проверок.

7
ответ дан 30 November 2019 в 07:09
поделиться

Вот тот, который я сделал только вчера. Дальнейшее размышление может привести меня изменять подход, но даже если так, "быстрый" подход позволил мне выполнить что-то, что я иначе не мог бы иметь.

Во-первых, некоторый фон. Я недавно изучил (здесь на StackOverflow) способ передать значение методу, таким образом, что метод сможет определить и имя и значение. Например, одно общее использование для проверки параметра. Например:

public void SomeMethod(Invoice lastMonthsInvoice)
{
     Helper.MustNotBeNull( ()=> lastMonthsInvoice);
}

Примечание там не является никакой строкой, содержащей "lastMonthsInvoice", который хорош, потому что строки сосут для рефакторинга. Однако в сообщении об ошибке может быть сказано, что что-то как "Параметр 'lastMonthsInvoice' не должно быть пустым". Вот сообщение, которое объясняет, почему это работает и указывает на сообщение в блоге парня.

Но это - просто фон. Я использую то же понятие, но по-другому. Я пишу некоторые модульные тесты, и я хочу разгрузить определенные значения свойств в консоль, таким образом, они обнаруживаются в выводе модульного теста. Я устал от записи этого:

Console.WriteLine("The property 'lastMonthsInvoice' has the value: " + lastMonthsInvoice.ToString());

... потому что я должен назвать свойство как строку и затем обратиться к нему. Таким образом, я сделал его, где я мог ввести это:

ConsoleHelper.WriteProperty( ()=> lastMonthsInvoice );

И получите этот вывод:

Property [lastMonthsInvoice] is: <whatever ToString from Invoice

производит>

Теперь, вот то, где быстрый подход позволил мне делать что-то, что я иначе не мог сделать.

Я хотел сделать ConsoleHelper. WriteProperty берут массив параметров, таким образом, он мог вывести много таких значений свойств к консоли. Чтобы сделать это, его подпись была бы похожа на это:

public static void WriteProperty<T>(params Expression<Func<T>>[] expr)

Таким образом, я мог сделать это:

ConsoleHelper.WriteProperty( ()=> lastMonthsInvoice, ()=> firstName, ()=> lastName );

Однако это не работает из-за вывода типа. Другими словами, все эти выражения не возвращают тот же тип. lastMonthsInvoice является Счет. firstName и lastName являются строками. Они не могут привыкнуть в том же вызове к WriteProperty, потому что T не является тем же через всех них.

Это - то, где быстрый подход пришел на помощь. Я сделал WriteProperty (), возвращают что-то. Тип, который это возвратило, является чем-то, на чем я могу звонить И (). Это дает мне этот синтаксис:

ConsoleHelper.WriteProperty( ()=> lastMonthsInvoice)
     .And( ()=> firstName)
     .And( ()=> lastName);

Это - случай, где быстрый подход позволил что-то, что иначе не будет возможно (или по крайней мере не удобно).

Вот полное внедрение. Как я сказал, я вчера записал это. Вы будете, вероятно, видеть простор для совершенствования или возможно еще лучшие подходы. Я приветствую это.

public static class ConsoleHelper
{
    // code where idea came from ...
    //public static void IsNotNull<T>(Expression<Func<T>> expr)
    //{
    // // expression value != default of T
    // if (!expr.Compile()().Equals(default(T)))
    // return;

    // var param = (MemberExpression)expr.Body;
    // throw new ArgumentNullException(param.Member.Name);
    //}

    public static PropertyWriter WriteProperty<T>(Expression<Func<T>> expr)
    {
        var param = (MemberExpression)expr.Body;
        Console.WriteLine("Property [" + param.Member.Name + "] = " + expr.Compile()());
        return null;
    }

    public static PropertyWriter And<T>(this PropertyWriter ignored, Expression<Func<T>> expr)
    {
        ConsoleHelper.WriteProperty(expr);
        return null;
    }

    public static void Blank(this PropertyWriter ignored)
    {
        Console.WriteLine();
    }
}

public class PropertyWriter
{
    /// <summary>
    /// It is not even possible to instantiate this class. It exists solely for hanging extension methods off.
    /// </summary>
    private PropertyWriter() { }
}
4
ответ дан 30 November 2019 в 07:09
поделиться

В дополнение к тем указанным здесь, платформа насмешки модульного теста popuplar RhinoMocks использует быстрый синтаксис для определения ожиданий по фиктивным объектам:

// Expect mock.FooBar method to be called with any paramter and have it invoke some method
Expect.Call(() => mock.FooBar(null))
    .IgnoreArguments()
    .WhenCalled(someCallbackHere);

// Tell mock.Baz property to return 5:
SetupResult.For(mock.Baz).Return(5);
3
ответ дан 30 November 2019 в 07:09
поделиться

SubSonic 2.1 имеет достойный для запроса API:

DB.Select()
  .From<User>()
  .Where(User.UserIdColumn).IsEqualTo(1)
  .ExecuteSingle<User>();

tweetsharp делает широкое применение быстрого API также:

var twitter = FluentTwitter.CreateRequest()
              .Configuration.CacheUntil(2.Minutes().FromNow())
              .Statuses().OnPublicTimeline().AsJson();

И Быстрый NHibernate является всем гневом в последнее время:

public class CatMap : ClassMap<Cat>  
{  
  public CatMap()  
  {  
    Id(x => x.Id);  
    Map(x => x.Name)  
      .WithLengthOf(16)  
      .Not.Nullable();  
    Map(x => x.Sex);  
    References(x => x.Mate);  
    HasMany(x => x.Kittens);  
  }  
}  

Ninject использует их также, но я не мог найти пример быстро.

2
ответ дан 30 November 2019 в 07:09
поделиться

Именование метода

Быстрые интерфейсы предоставляют себя удобочитаемости, пока имена методов выбраны разумно.

Имея это в виду, я хотел бы назначить этот конкретный API "антибыстрым":

Система. Ввести. IsInstanceOfType

Это - член System.Type и берет объект и возвращает true, если объект является экземпляром типа. К сожалению, Вы естественно склонны читать его слева направо как это:

o.IsInstanceOfType(t);  // wrong

Когда это - на самом деле другой путь:

t.IsInstanceOfType(o);  // right, but counter-intuitive

Но не все методы мог возможно быть назван (или расположен в BCL) ожидать, как они могли бы появиться в "псевдоанглийском" коде, таким образом, это не действительно критика. Я просто указываю на другой аспект быстрых интерфейсов - выбор имен методов для порождения наименьшего количества удивления.

Объектные инициализаторы

Со многими примерами, данными здесь, единственная причина, быстрый интерфейс используется, состоит в том так, чтобы несколько свойств недавно выделенного объекта могли быть инициализированы в отдельном выражении.

Но C# имеет функцию языка, которая очень часто делает это ненужным - объектный синтаксис инициализатора:

var myObj = new MyClass
            {
                SomeProperty = 5,
                Another = true,
                Complain = str => MessageBox.Show(str),
            };

Это, возможно, объяснило бы, почему опытные пользователи C# менее знакомы с термином "быстрый интерфейс" для объединения в цепочку запросов к тому же объекту - это не необходимо вполне так часто в C#.

Поскольку свойства могли кодировать рукой методы set, это - возможность назвать несколько методов на недавно созданном объекте, не имея необходимость заставлять каждый метод возвратить тот же объект.

Ограничения:

  • Метод set свойства может только принять один аргумент
  • Метод set свойства не может быть универсальным

Я хотел бы его, если мы могли бы назвать методы и поступить на службу в события, а также присвоить свойствам в объектном блоке инициализатора.

var myObj = new MyClass
            {
                SomeProperty = 5,
                Another = true,
                Complain = str => MessageBox.Show(str),
                DoSomething()
                Click += (se, ev) => MessageBox.Show("Clicked!"),
            };

И почему такой блок модификаций должен только сразу быть применимым после конструкции? Мы могли иметь:

myObj with
{
    SomeProperty = 5,
    Another = true,
    Complain = str => MessageBox.Show(str),
    DoSomething(),
    Click += (se, ev) => MessageBox.Show("Clicked!"),
}

with было бы новое ключевое слово, которое воздействует на объект некоторого типа и производит тот же объект, и тип - отмечают, что это было бы выражением, не оператором. Таким образом, это точно получило бы идею объединить в цепочку в "быстром интерфейсе".

Таким образом, Вы могли использовать синтаксис стиля инициализатора независимо от того, был ли у Вас объект от a new выражение или из МОК или метода фабрики, и т.д.

На самом деле Вы могли использовать with после полного new и это было бы эквивалентно текущему стилю объектного инициализатора:

var myObj = new MyClass() with
            {
                SomeProperty = 5,
                Another = true,
                Complain = str => MessageBox.Show(str),
                DoSomething(),
                Click += (se, ev) => MessageBox.Show("Clicked!"),
            };

И поскольку Charlie указывает в комментариях:

public static T With(this T with, Action<T> action)
{
    if (with != null)
        action(with);
    return with;
}

Вышеупомянутая обертка просто вынуждает действие невозврата возвратить что-то, и эй престо - что-либо может быть "быстрым" в этом смысле.

Эквивалентный из инициализатора, но с включением в список события:

var myObj = new MyClass().With(w =>
            {
                w.SomeProperty = 5;
                w.Another = true;
                w.Click += (se, ev) => MessageBox.Show("Clicked!");
            };

И на методе фабрики вместо a new:

var myObj = Factory.Alloc().With(w =>
            {
                w.SomeProperty = 5;
                w.Another = true;
                w.Click += (se, ev) => MessageBox.Show("Clicked!");
            };

Я не мог сопротивляться предоставлению его, "возможно, монада" - разрабатывает проверку на пустой указатель также, поэтому если у Вас есть что-то, что могло бы возвратиться null, можно все еще подать заявку With к нему и затем проверяют его на null- мыс.

3
ответ дан 30 November 2019 в 07:09
поделиться

API Критериев в NHibernate имеет хороший быстрый интерфейс, который позволяет Вам делать интересный материал как это:

Session.CreateCriteria(typeof(Entity))
    .Add(Restrictions.Eq("EntityId", entityId))
    .CreateAlias("Address", "Address")
    .Add(Restrictions.Le("Address.StartDate", effectiveDate))
    .Add(Restrictions.Disjunction()
        .Add(Restrictions.IsNull("Address.EndDate"))
        .Add(Restrictions.Ge("Address.EndDate", effectiveDate)))
    .UniqueResult<Entity>();
1
ответ дан 30 November 2019 в 07:09
поделиться

Новым HttpClient Предварительного просмотра Стартового набора REST WCF 2 является большой быстрый API. посмотрите мое сообщение в блоге для демонстрационного http://bendewey.wordpress.com/2009/03/14/connecting-to-live-search-using-the-httpclient/

1
ответ дан 30 November 2019 в 07:09
поделиться

Как @John Sheehan упомянул, Ninject использует этот тип API для определения привязки. Вот некоторый пример кода из их руководства пользователя:

Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf();
Bind<Shogun>().ToSelf().Using<SingletonBehavior>();
0
ответ дан 30 November 2019 в 07:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: