Продолжаем кодить на C#. «Hello, world!» в контейнере.

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Вечер в хату, автоматизаторы всего и вся!
92264


Данное писание можно считать продолжением статьи «Начинаем кодить на c#» от господина @Brabus_bots.
Собственно, это для тех, кому было мало, и, кто ищет новые подходы к разработке...:-)

Долго ходить вокруг да около не буду, начну сразу лить воду, готовьтесь принимать душ…
(ʘ ͜ʖ ʘ)

Вот мы уже знаем, что такое переменные, циклы и goto, который не раз выстреливал нам в левое колено…
Да и вообще мы крутые ребята, которые умеют писать “Hello, world” закрытыми глазами!
Но всё-таки мы - зеннолабовцы - с форума «Сообщество профессионалов автоматизации», а значит нам всегда хочется знать больше!
Мы хотим покорять новые горизонты! Что ж, погнали! Время писать «Hello, world!» используя контейнеры
(⊙ˍ⊙)


Что у нас по плану?
  • Кто такой этот магический кубик «Проект Visual Studio»
  • Познакомиться с Dependency Injection (DI), IoC-контейнерами и зачем оно нам нужно...
  • Напишем мелкий и бесполезный проект в Visual Studio 2022 для демонстрации использования DI

Если вам здесь всё понятно, то проблем в понимании материала ниже возникнуть не должно.
Код обычного C# кубика:
// дёргаем локальный метод для отправки полученного текста в лог
Print(GetTextFromSite());

// отправка сообщения в лог
void Print(string sendText)
{
    project.SendToLog(sendText, ZennoLab.InterfacesLibrary.Enums.Log.LogType.Info, true, ZennoLab.InterfacesLibrary.Enums.Log.LogColor.Green);
}

// получение текста текста с сайта
string GetTextFromSite()
{
    // получаем страницу вики
    var doc = new Global.Zennolab.HtmlAgilityPack.HtmlWeb().Load("https://en.wikipedia.org/wiki/%22Hello,_World!%22_program");
    
    // получаем текст по xPath
    var hw = doc.DocumentNode?.SelectSingleNode("//div[contains(@id, 'content')]/descendant::div[contains([USER=46442]@class[/USER], 'c#')]")?.InnerText;
    
    // выдёргиваем нужное регуляркой и возвращаем
    return hw != null ? Regex.Match(hw, @"(?<=&quot;).*?(?=&quot;)").Value : string.Empty;
}


Начнем с небольшой теории, для большего понимания:
Универсальный узел - инкапсулирует все ресурсы приложения и функциональные возможности времени существования
(согласен, мелкомягкие пишут как-то страшно, но всё, что нам нужно будет – пихнуть заранее созданную конфигурацию сервисов в "IHostBuilder" и всё забилдить ключевым словом "Build").

Инкапсуляция – механизм сокрытия какой-либо реализации/деталей от лишних глаз и предоставление итоговому клиенту
только того функционала, который мы задумывали (для этого используются модификаторы доступа, такие как: private, internal, public и т.д.).
92270


Dependency Injection (DI) – процесс предоставления внешней зависимости программному компоненту.
В проекте, осуществлять инъекции будем через конструктор класса. Следует знать, что это не единственная возможность,
есть и другие способы: инъекция через метод и свойств, но, как говорил мой сэмпай - “это бэд практис” -
¯\_(ツ)_/¯.

Зависимость — это любой объект, от которого зависит другой объект (например, если мы в методе используем инстанс зенки,
то сам метод будет зависим от этого инстанса зенки, получается, инстанс – наша внешняя зависимость).

IoC-контейнер — это библиотека/фреймворк которая позволит нам упростить и автоматизировать написание кода с использованием данного подхода.
Она будет создавать и предоставлять нам готовые инстансы в проекте (если мы их конечно же зарегистрировали в конфиге).
Основные IoC библиотеки, которые предоставляют нам магию: «Microsoft.Extensions.DependencyInjection» и «Autofac» (мы будем использовать реализацию от Microsoft).

Интерфейс – это контракт, некая абстракция, который должен реализовать класс (например, в созданном проекте,
у нас есть класс “Program”, который реализует интерфейс “IZennoExternalCode”, то есть, “Program” должен по контракту реализовать
метод “Execute”, который прописан в интерфейсе “IZennoExternalCode”, а как именно это будет реализовано – уже наша забота,
а не разработчиков ZennoPoster (они и так лапочки).


Подготовка инструментов:
(1) Медлить не будем, поэтому, сразу врываемся с ноги на сайт Microsoft, вежливо говорим “Ня, аригато”, качаем Visual Studio 2022 и устанавливаем её по инструкциям из интернетов.
92231

92233


Запускаем скаченный “Visual Studio Setup” и выбираем “.NET Desktop Development” (не уверен, но этого должно хватить)
92236


Проекты для ZP у нас будут создаваться на древнем .NET Framework 4.6.2, так что, на всякий случай ставим эти пакеты тоже.
92240

Тыкаем "Install" (у меня "Modify", так, как студия уже установлена)
Создаём новый проект (сама студия должна быть закрыта)
92241

92242

92243

92244

92245


Нашёл оригинал по вопросику (?) в правом верхнем углу:
Проект Visual Studio - Русская справка Zennolab - Confluence (atlassian.net)

(2) Создаём новый проект в “ProjectMaker” и добавляем сие чудо-кубик.
92246


(3) Кликаем на создание нового проекта в свойствах кубика.
92247


(4)Заполняем поля и кликаем “OK”
92248

“Название решения” – даём более общее название, ибо там может быть много проектов (решение – это то, что объединяет проекты).
“Название проекта” – даём более конкретное название, там будет наш код (повторять название, как я – не обязательно, просто люблю такое соблюдение неймспейсов).

То есть, такое именование будет так же корректным.
92249


А вот и произошла магия - наш первый проект в Visual Studio создан.
92271


П.С. Наши свойства кубика будут заполнены автоматически и в будущем мы сможем спокойно подключаться к проекту.
92252



Примечание:
Замечу, мы должны выставить в ProjectMaker и Visual Studio тёмную тему.
Для чего? Ходят слухи, что иначе программы могут работать некорректно…
(⊙ˍ⊙)
Сделали?! Ну всё, теперь, мы точно готовы двигаться дальше…(¬‿¬)


Практика:
92261


Вообще, всё интуитивно понятно, но пакеты тут, если что
92263
92253

(1)
Я создал тут папочку для вас, в которую добавил новый статический класс.
(2) Так же добавляем в него юзинг установленной библиотеки для работы с IoC.
(3) В классе добавляем статический метод расширения для "IServiceCollection", где будет проходить наша регистрация сервисов
для последующего предоставления в качестве внешних зависимостей. На данный момент, там зарегистрированы: инстанс браузера и инстанс зенки.

92254

(1) Ключевое слово “this”, в данном контексте, говорит нам о том, что это метод расширения, а расширяем мы "IServiceCollection".
То есть, когда в следующий раз, мы тыкнем « . » после объекта типа "IServiceCollection" (правильнее сказать, объекта, который реализовывает данный интерфейс,
но нам это знать сейчас не обязательно), то у нас будет доступен наш метод “AddApplication” в который мы должны будем передать "Instance" и "IZennoPosterProjectModel"
(первый параметры – IServiceCollection – передавать не нужно, поскольку, именно у его мы вызываем этот метод и он будет передан автоматически).
П.С. Методы расширения могут быть только в статическом классе и статическом методе.
(2) Тут мы добавляем/регистрируем наши сервисы/инстансы в рамках жизненного цикла называемого “Scoped
(он, кстати, написан тоже, как метод расширения; это видно на всплывашке при наведении курсора на метод и ключевому слову “extension”).
Transient (AddTransient) - инстанс сервиса создается каждый раз, когда его запрашивают. Этот жизненный цикл лучше всего подходит для легковесных, не фиксирующих состояние, сервисов.
Scoped (AddScoped) - инстанс сервиса создается единожды для каждого запроса.
Singleton (AddSingleton) - инстанс сервиса создается при первом запросе (или при запуске ConfigureServices, если вы указываете инстанс там), а затем каждый последующий запрос будет использовать этот же инстанс.

Источник: Разница между AddTransient, AddScoped и AddSingleton в ASP.NET Core / Хабр (habr.com)

Могу ошибаться, но, в рамках зенки, "Scoped" и "Singleton" - будет практически одно и тоже.
(3) "IServiceCollection" – это возвращаемый тип (то есть, мы используем метод расширения для "IServiceCollection" и его же возвращаем, таким образом, это образует Fluent Interface/Fluent Api).
(4) Всё это входные параметры метода (сигнатура метода).

Ещё чуть-чуть разжую, на всякий…)
92255

(1) Это сервисы, которые мы регистрируем.
(2) А это мы запихиваем готовые инстансы этих сервисов (обычно, контейнер сам нам создает и предоставляет инстансы, но, в данном случае,
нам нужны уже готовые, которые пришли прямиком из ZennoPoster или ProjectMaker).

Чтоб всё у нас завелось - я вернулся в наш класс “Program” и…
92256

(1) Добавляем юзинг хостинга (пакета, который мы ранее должны были установить).
(2) Так же добавляем стандартный метод для создания хост билдера, в который передаём инстансы пришедшие из зенки.
(3) И именно тут используем наш, выше написанный, метод расширения.
services” – это и есть тот самый первый параметр “IServiceCollection” (можете сами потом убедиться, наведя мышку на этот объект).
(4) Разумеется, вызываем метод для создания хост билдера.
(5) А следом вызываем и метод сборки.

Всё! Теперь наш контейнер сможет нам творить магию в виде инъекций инстансов зарегистрированных сервисов в конструкторы классов,
то бишь, будет предоставлять нам внешние зависимости
(~ ̄▽ ̄)~
Собственно, толку пока не много, нужно вывести наш первый “Hello, world!”


«Hello, world!» в контейнере:

92257

(1) Собственно, мы создали наш первый условный сервис (да, обычный класс).
(2) Добавили метод “Run”, который будем вызывать для старта сервиса (название может быть любым).
(3) Добавили конструктор класса, именно сюда IoC будет производить нашу инъекцию, когда мы обратимся к методу “Run”.
Заметьте, что у конструктора класса “0 references”, а это значит, что на него никто не ссылается, а он будет вызваться…
Что-то это, если не магия?! Атеистам шах и мат!
(⊙_(⊙_⊙)_⊙)

92258

(1) Теперь регистрируем созданный сервис в нашем регистраторе.
Опять же, обратите внимание, что никакого инстанса мы не пихаем,
IoC за нас будет создавать его и предоставлять конструктору нужные внешние зависимости.
Получается так, что в конструкторе сервиса (созданном нами классе) мы можем использовать любой порядок внешних зависимостей.

92259

(1) Всё, теперь нам требуется просто запросить наш сервис у хоста (если быть точным, то у "IServiceProvider", который обитает в свойствах "IHost".
Не устану повторять: мы запрашиваем сервис у которого есть конструктор, но ничего не передаём для самого конструктора, IoC сам всё сделает исходя из конфига.
По поводу "IServiceProvider": мы так же можем использовать его в конструкторах не статических классов, если нам потребуется
выдернуть какой-то инстанс сервиса похожим образом, при этом, не нужно заранее регистрировать "IServiceProvider" в нашем конфиге, он уже зарегистрирован под капотом.
(2) И вызвать тот самый метод “Run

Теперь просто запускаем проект в зенке и наблюдаем за нашим итоговым результатом - «Hello, world!» - в контейнере!
92260


Задачка на подумать: это не обязательно, но, в идеале, теперь неплохо бы было избавиться от завязки на реализации,
и завязаться на абстракции, то есть, на интерфейсе, например “IHelloWorldService”, а как это сделать – придётся решать вам самим.


¯\_( ͡° ͜ʖ ͡°)_/¯

Резюме по Dependency Injection и IoC-контейнеру:
DI и IoC – вещи не сложные, но это прям то, что доктор прописал для больших проектов
планируемых расширяться в будущем (для мелких так же подойдёт), где есть куча зависимостей и сложной реализации и т.д.
Данный подход к разработке проекта: упрощает написание кода, делает его более гибким, поддерживаемым, расширяемым и более приятным.
К тому же, не нужно беспокоиться за стейт объектов и хранить всё по статическим переменным /ᐠ。ꞈ。ᐟ\

Резюме по кубику “Проект Visual Studio”:
Очевидно, что данная фича будет очень полезна тем, кто начал начал использовать C# в своих проектах.
Разработчики ZennoPoster делают шаги в правильном направлении (осталось открыть API
для решения ReCaptcha2 из Visual Studio, - цены бы вам тогда не было).
Написание проектов в VS ускоряет и упрощает разработку за счёт умного "Интеллисенс", а "Nuget package manager" - открывает доступ к огромному количеству библиотек,
да и дебажить в студии просто волшебно (◡‿◡)


П.С. Это была моя первая статья, и это был лишь косплей на программиста, не судите строго...:-)
92266



Visual Studio 2022 v17.2.1
ZennoPoster v7.7.1.0
(это минимальная версия для поддержки 22-й студии)
 
Тема статьи
Нестандартные хаки, Парсинг, Другое
Номер конкурса статей
Семнадцатый конкурс статей

Вложения

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

Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

Последнее редактирование:

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
92361
 
Последнее редактирование:

semafor

Client
Регистрация
27.12.2016
Сообщения
289
Благодарностей
404
Баллы
63
  • Спасибо
Реакции: SHILY

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Последнее редактирование:

sergio197675

Client
Регистрация
21.09.2019
Сообщения
360
Благодарностей
318
Баллы
63
ну всё , теперь точно в адепты C# вступлю
Спасибо!
 
  • Спасибо
Реакции: SHILY

radv

Client
Регистрация
11.05.2015
Сообщения
3 788
Благодарностей
1 952
Баллы
113
Ну вот и статья про использование визуалстудио из зенки ) :ay:
 
  • Спасибо
Реакции: SHILY

radv

Client
Регистрация
11.05.2015
Сообщения
3 788
Благодарностей
1 952
Баллы
113

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63

sergio197675

Client
Регистрация
21.09.2019
Сообщения
360
Благодарностей
318
Баллы
63
А ты разве не учил его? ))
не углубляясь, пока на уровне "поправить готовое под себя"
но если переварю всё и полерну, предоставленным курсом от Sama , то тоже буду умничать на форуме ( в хорошем смысле этого слова) :D
 
  • Спасибо
Реакции: kriptochel1996

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63

radv

Client
Регистрация
11.05.2015
Сообщения
3 788
Благодарностей
1 952
Баллы
113
Ага, невероятно удобно стало работать:al:
Поздравляю. а я так по привычке напрямую в студии работаю, а потом в общий код переношу. Не было желания разбираться с нюансами, почему не срабатывало подключение к студии из зенки.
 

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Поздравляю. а я так по привычке напрямую в студии работаю, а потом в общий код переношу. Не было желания разбираться с нюансами, почему не срабатывало подключение к студии из зенки.
У меня, кстати, на новой версии студии отвалилось подключение, но это не мешает писать и запускать проект. Сейчас как раз нужно сделать диагностику и кинуть, чтоб проверили в чём дело.
 

radv

Client
Регистрация
11.05.2015
Сообщения
3 788
Благодарностей
1 952
Баллы
113
У меня, кстати, на новой версии студии отвалилось подключение, но это не мешает писать и запускать проект. Сейчас как раз нужно сделать диагностику и кинуть, чтоб проверили в чём дело.
Ну значит и париться не буду с таким подключением, пока не заработает нормально )
 

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Ну значит и париться не буду с таким подключением, пока не заработает нормально )
Ага, мне просто неудобно держать две студии (19 и 22), так что, пришлось на тестовый билд сесть, ибо у меня VS 2022. Всё было хорошо, пока студия не обновилась до 17.2 :-)
 

radv

Client
Регистрация
11.05.2015
Сообщения
3 788
Благодарностей
1 952
Баллы
113
  • Спасибо
Реакции: SHILY

cmvvo

Client
Регистрация
07.07.2019
Сообщения
38
Благодарностей
16
Баллы
8
Полезно! голосую :bu:
 
  • Спасибо
Реакции: SHILY

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Регистрация
05.06.2019
Сообщения
570
Благодарностей
454
Баллы
63
айй красавчик!!!)

кто не в теме, рекомендую

92283
 

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
  • Спасибо
Реакции: Маломальский

Sanekk

Client
Регистрация
24.06.2016
Сообщения
999
Благодарностей
390
Баллы
63
ТС плюс в карму, разжевал подробно и статья читается легко и понятно
 
  • Спасибо
Реакции: SHILY

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Последнее редактирование:

Zedx

Client
Регистрация
12.06.2018
Сообщения
1 346
Благодарностей
910
Баллы
113
У меня, кстати, на новой версии студии отвалилось подключение, но это не мешает писать и запускать проект. Сейчас как раз нужно сделать диагностику и кинуть, чтоб проверили в чём дело.
На последнем тестовом билде, выложенном пару дней назад проблему с VS2022 исправили, до этого у меня она тоже не работала.
 
  • Спасибо
Реакции: SHILY
Регистрация
26.05.2020
Сообщения
495
Благодарностей
172
Баллы
43
Вот прям чувствую, что мегаполезная статья! Лайкнул, хоть нихуя и не понял! Нужно откатиться, потом вернуться!
 

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
На последнем тестовом билде, выложенном пару дней назад проблему с VS2022 исправили, до этого у меня она тоже не работала.
Да, я его тестил, но мне не помогло, вот кинул репорты недавно:-)
 

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Вот прям чувствую, что мегаполезная статья! Лайкнул, хоть нихуя и не понял! Нужно откатиться, потом вернуться!
Я поделился своим опытом/подходом, после того, как без DI похоронил проект на 10к строчек кода, где "шаг вправо, шаг влево - расстрел", так что, должно быть полезным, надеюсь:D
 
Последнее редактирование:

Serjio Leone

Client
Регистрация
20.09.2017
Сообщения
114
Благодарностей
84
Баллы
28
Спасибо! Интересная статья. :-)
А по поводу открыть API для решения ReCaptcha2 - нужно голосовать
 
  • Спасибо
Реакции: SHILY

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
  • Спасибо
Реакции: Serjio Leone

usawa0

Client
Регистрация
29.11.2019
Сообщения
59
Благодарностей
22
Баллы
8
Четко! Как раз не хватало разбора работы с визуалкой. Постараюсь все это прикрутить к VS19. На VS2022 пока не тянет
 
  • Спасибо
Реакции: SHILY
Регистрация
01.04.2022
Сообщения
24
Благодарностей
3
Баллы
3
не углубляясь, пока на уровне "поправить готовое под себя"
но если переварю всё и полерну, предоставленным курсом от Sama , то тоже буду умничать на форуме ( в хорошем смысле этого слова) :D
Кто такой Sama и что за курс?
 

SHILY

Client
Регистрация
05.06.2016
Сообщения
258
Благодарностей
307
Баллы
63
Четко! Как раз не хватало разбора работы с визуалкой. Постараюсь все это прикрутить к VS19. На VS2022 пока не тянет
Спасибо! Да на 19-й должно всё нормально работать :-)
 

Кто просматривает тему: (Всего: 3, Пользователи: 0, Гости: 3)