#1
Я не программист. Это значит, что некоторые вещи я могу объяснять неправильно, могу упускать какие-то важные моменты, могу не оптимально писать код, могу даже неверно использовать терминологию. Это не профессиональный курс.
Я уже несколько лет использую c# в ZennoPoster. Моя основная задача – это максимально простое объяснение материала. Мне нужно, чтобы вы поняли C# и начали использовать в своих шаблонах, а дальше уже при желании можете проходить уроки программистов (на том же ютубе или metanit), если вам это нужно.
И ещё момент – я буду работать в обычном кубике C#, а не Visual Studio. Дело в том, что я не программист и потому никогда особо не пользовался VS. Раньше его не было, и я привык работать так.
Есть несколько причин, по которым я не пытаюсь перейти на VS:
- Если вы работаете в VS, то вы весь проект будете писать на C#. Тут нужно учитывать, что далеко не все кубики имеют аналог на C#. Кроме того, некоторые вещи банально удобнее делать на кубиках, плюс вы первое время в любом случае будете совмещать у себя и то и другое.
- В VS есть свои баги, которые надо уметь отлавливать (я имею ввиду в связке с ZennoPoster). Возможно сейчас это уже всё пофиксили, но раньше они точно были. Даже те, кто юзает VS, чаще всего пишут проект там, а потом переносят всё равно переносят в общий код
- Лично мне неудобно тестировать проект. Мне не нравится, как они вставили браузерное окно в VS.
То, что я показываю вам в кубике C#, будет работать и VS (главное правильно его подключить - https://zennolab.atlassian.net/wiki/spaces/RU/pages/1375109121/Visual+Studio). Если вам удобнее тренироваться там, я не против.
Классы и объекты
Частенько объясняют так. Класс – это некий чертёж, а объектом будут уже конкретные вещи, которые по этому чертежу создаются.
Возьмём для примера человека. Человек – это класс (class).
У него есть рост, вес, цвет волос, количество пальцев и т.д. Т.е. какое-то описание. Всё это – свойства (properties).
Также человек может ходить, бегать, прыгать, читать, писать и т.д. Т.е. какие-то действия. Это всё – методы (methods).
А вот Вася Пупкин 27 лет или Елена Ивановна 20 лет – это уже объекты, экземпляры класса человек.
Возьмём теперь автомобили. Автомобиль = class. Они у нас имеют цвет, мощность, тип и т.д. Это свойства. Автомобиль может ехать. Это метод. А ВАЗ 2107 будет объектом, экземпляром класса автомобиль.
Поняли?
А теперь перенесёмся в контекст языка C#. Нам с вами доступна большая библиотека классов "из коробки" (Net Framework). Например, класс для работы с датой и временем (DateTime), класс для работы с файлами (FileInfo), класс для работы с папками (DirectoryInfo) и ещё 100500 таких классов. Некоторые из этих классов уже подключены по умолчанию и можно сразу начинать их вызывать. Другие же нужно сначала подключить, но об этом в другой раз.
Кроме того, что доступно "из коробки", у нас есть классы от разработчиков команды ZennoLab. Посмотреть их можно тут - https://help.zennolab.com/en/v7/zennoposter/7.1.4/webframe.html#topic1.html
Пораскрывайте папки и увидите надпись class. Ага, вот и наши классы.
Например, «HtmlElement» нужен для работы с отдельными элементами, которые мы находим на странице. Вы можете узнать ширину и высоту элемента (1), получить его местоположение относительно верхнего края браузера (2), получить имя тэга (3), получить текст (4), проверить существование (5) и т.д. Это всё свойства.
Теперь посмотрим методы. Мы можем кликнуть по элементу(1), перетащить элемент (2), получить его потомков (3) и т.д. Имейте ввиду, что методы (в отличии от свойств) имеют круглые скобки на конце.
Аналогично с другими объектами (классами). Так, «instance» - это браузер. Мы можем получить все вкладки, узнать или установить таймзону, получить или установить куки, установить разрешение и т.д. «tab» - это вкладка браузера. Здесь мы можем находить элементы, двигать мышку, эмулировать клавиатуру.
Помимо "базовой коробки" и "коробки от ZennoLab" мы можем ставить и сторонние библиотеки от какого-нибудь программиста Пети.
Почему я акцентировал на этом внимание. Смотрите, сейчас популярны нейросети, помогающие писать код. Так вот, он хорошо разбирается в "базовой коробке", но очень мало знает о том, что там написали разработчики ZennoLab или какой-то Петя (если только библиотека Пети не стала популярной). Поэтому имейте это ввиду, когда обращаетесь к AI за помощью.
Есть и ещё один момент, о котором стоит упомянуть. Наша "базовая коробка" (уж извините за такой слэнг) всё время пополняется новыми классами, т.е. новым функционалом. Но конкретно в ZennoPoster этого самого обновления не происходит. Мы застряли на .Net Framework (конкретную версию не помню), которая отстаёт от мира на пару лет. Это не страшно, но имейте ввиду, что если ваш код не запускается на ZennoPoster, то или не подключены нужные библиотеки или они в принципе не поддерживаются в ZennoPoster.
На самом деле всё не так страшно, потом это в голове уложится. Всё, что будет даваться в статье, будет работать сразу, так что можете открывать кубик c#, вставлять туда код и смотреть, как это работает.
Основы написания кода
Итак, давайте вникать в тему. Мы с вами знаем, что есть некие классы, у которых есть свойства и методы, позволяющие делать всякие штуки. Т.к. класс это чертеж, то нам нужно сначала создать конкретный экземляр данного класса (объект) и уже него мы просить что-либо сделать.
Давайте потренируемся на Windows Forms. Вы можете использовать формы вместо входных настроек. Также они могут быть полезны, если, например, нужно вручную указать какой-то код для сайта (например, при авторизации в телеграмм или whatsapp).
Есть такой класс как Form, позволяющий работать с формами. Его полное имя System.Windows.Forms.Form. Первым делом создадим по этому чертежу конкретного "Васю Пупкина". Формула тут такая:
|
System.Windows.Forms.Form form = new System.Windows.Forms.Form(); |
form – это имя экземпляра класса (объекта). Оно может быть любым (почти). Т.е. вместо form вы можете написать zenno, superForm и т.д.
Обратите внимание, что на конце нужно всегда ставить точку с запятой.
Теперь вот по этому имени мы и будем обращаться. С помощью свойств width и height зададим ширину и высоту нашей формы, а с помощью метода showDialog() заставим форму отобразиться.
Итак, со следующей строчки обращаемся по тому имени, что мы задали
form. |
Мы видим тут свойства (значок гаечного ключа), методы (значок фиолетовой коробки) и некотороые другие вещи, на которых пока не будем акцентировать внимание. Выбираем свойство Width и жмем Enter (или щелкаем два раза мышкой). Теперь прописываем ту ширину, которая нам нужна.
form.Width = 400; |
form.Height = 550; |
form.ShowDialog(); |
C#:
System.Windows.Forms.Form form = new System.Windows.Forms.Form();
form.Width = 400;
form.Height = 550;
form.ShowDialog();
Теперь добавим туда поле для ввода нашего кода и сохраним результат в переменную. Для этого используется уже отдельный класс TextBox. Код целиком
C#:
System.Windows.Forms.Form form = new System.Windows.Forms.Form();
form.Width = 400;
form.Height = 550;
System.Windows.Forms.TextBox smsBox = new System.Windows.Forms.TextBox();
smsBox.Left = 100; //отступ слева
smsBox.Top = 50; //отступ сверху
smsBox.Width = 150; //ширина поля
form.Controls.Add(smsBox); //добавляем созданную кнопку на поле
form.ShowDialog(); //отображаем форму
project.Variables["result"].Value = smsBox.Text; //записываем введенное значение в переменную result (создайте ее вручную, как всегда это делаете)
Если вам хочется углубиться в создание форм, читайте эту статью - https://zenno.club/discussion/threads/okna-winforms-na-csharp-login-i-parol-sms-kod-knopka-prodolzhit-shablon.116652/
Продолжаем разбираться
В некоторых случаях нам не требуется создавать экземляр класса. Т.е. нам не понадобится ранее упомянутая конструкция вида
Название_Класса любое_имя = new Название_Класса(); |
Мы будем обращаться сразу же по названию класса
Название_Класса.метод(); |
или
Название_Класса.Свойство; |
Давайте напишем в кубике c# следующее
instance. |
instance – это у нас класс от разработчиков ZennoLab для работы с браузером. Тут нам не нужно писать что-то вроде
Instance name = new Instance();
Мы сразу же пишем instance и выбираем то свойство или метод, который нам нужен.
Если мы используем свойство, нам не нужно будет ставить скобки и оно что-то нам вернёт, например:
project.Variables["result"].Value = instance.CachePath; //в переменную result ляжет путь к кэшу браузера
А вот в методах скобки уже нужны, и они что-то делают. Они тоже могут что-то возвращать после своей работы, но не всегда
instance.Reload(); //перезагрузка браузера
Вот так мы можем с вами очистить кэш (1 строка), куки (2 строка) и прокси (3 строка).
C#:
instance.ClearCache();
instance.ClearCookie();
instance.ClearProxy();
Название_класса любое_имя = Название_другого_класса.свойство; |
Tab tab = instance.ActiveTab;
Теперь мы можем обращаться по тому имени, которое придумали (tab). Положим в переменную result исходный код страницы (DOM). Код целиком с самого начала
C#:
Tab tab = instance.ActiveTab;
project.Variables["result"].Value = tab.DomText;
Т.е. свойство DomText класса Tab возвращает нам DOM страницы.
Надеюсь, ваши мозги не закипели. Я честно хотел отойти от теории, но как-то не получается. Можно конечно тупо писать код, но мне как-то хотелось, чтобы у вас с самого начала было некое понимание, что происходит.
И ещё одно - все классы хранятся внутри пространства имён (namespace). Пока условимся, что пространство имён – просто некая коробка для хранения классов. Например, большинство классов от разработчиков ZennoPoster лежат внутри пространства имен под названием "ZennoLab.CommandCenter".
Давайте подытожим, что мы узнали на текущий момент:
- В c# есть готовые классы, предлагающие ту или иную функциональность.
- Чтобы нам что-то сделать, надо получить доступ к объекту класса. Иногда нужно создавать экземпляр класса (через new), иногда мы обращаемся сразу по названию, иногда мы получаем его из свойств и методов другого класса.
- После этого мы можем использовать свойства и методы этого класса.
- Также мы уже умеем с вами создавать экземпляры класса Form, instance, Tab. Умеем вызывать некоторые их свойства и методы
#2
Давайте теперь немного разграничим такие понятия как класс, объект, тип данных и переменная.
Класс (class) – это некий чертёж, по которому создаются объекты. Например, если у нас класс человек, то объектом уже будет конкретный Вася Пупкин, Иван Иванов и т.д.
Объект, соответственно, это уже конкретный экземпляр класса.
Переменная – просто некая "коробка", которая хранит данные. Например, мы взяли из списка прокси и нам надо его куда-то положить. Как раз в переменную мы его и положим.
Тип данных же определяет, какого именно типа данные хранятся в переменной. Например, прокси мы будем хранить в строковом типе данных string, а вот возраст уже в числовом типе int.
Запоминать это особо не нужно, так, больше для справки. Это даже не официальные определения. Кому важна точность, лучше погуглить. Позже будете интуитивно всё это понимать. Я вообще постараюсь употреблять поменьше профессиональных терминов, ибо сам в них не особо разбираюсь (помните, я не программист). Главное понять суть, как нам работать.
В C# данные условно делятся на простые (строки, числа, …) и сложные (объекты, структуры, …).
В C# есть следующие простые типы данных:
- Строка (string). Заключается в двойные кавычки
- Число (byte, sbyte, short, ushort, int, uint, long, ulong, float, double, decimal)
- Булевое значение (bool). Принимает только два значения: true (правда) или false (ложь)
- char. Один символ
Отступление
Прежде чем перейти к рассмотрению простых типов данных, рассмотрим комментарии и вывод информации в лог.
Комментарии нужны чтобы оставлять себе подсказки в коде. Они никак не влияют на выполнение. Помечаются зеленым цветом в редакторе.
Однострочный комментарий обозначает двумя косыми чертами
//я комментарий
Многострочные косой чертой и звездочкой
C#:
/*
Я многострочный комментарий.
Можно писать что угодно пока вы его не закроете
*/
project.SendInfoToLog("Выводим сообщение в лог ZennoPoster");
Не стоит принимать мои слова на веру, проверяйте всё на практике. Весь код, который вы видите в рамке, вы можете вставлять в кубик c# и смотреть, что происходит. Скопируйте строку выше и вставьте в C# кубик. Появилась ли информация в логе?
P.S. Если кто из старичков вдруг захочет поворчать, что project это вообще не class, а interface, то я в курсе, однако это не играет никакого значения. Сейчас (да и потом) забивать этим голову нет смысла, поэтому я буду называть project именно классом.
P.P.S. Если кто будет проходить уроки в ютубе или читать статьи про c#, то там вы метод SendInfoToLog() не встретите, т.к. он у нас от разработчиков ZennoPoster. В Visual Studio используется Console.WriteLine(), который похож на наш метод. Чтобы вам потестить примеры из статей в project maker, надо просто заменить Console.WriteLine на project.SendInfoToLog.
Переменные
Давайте чтобы в голове не возникала каша разберемся с этим подробнее. Начнем с кубиков. Мы с вами создаем переменные вот так
И далее помещаем в эту "коробку" уже какую-то информацию (прокси, данные со страницы, пути к файлам и т.д.).
Когда мы работаем с этими переменными, мы вообще не задумываемся о типе данных. Т.е. мы можем класть туда что угодно: числа, строки, true/false, даты и т.д. В c# же нам надо следить за тем типом данных, который мы используем.
Я буду называть эти переменные "переменные уровня проекта". Их можно использовать в кубике c#. Вот так мы можем положить туда значение "Вася":
project.Variables["result"].Value = "Вася";
Т.е. обращение к "переменным уровня проекта" происходит с помощью конструкции
project.Variables["имя_переменной"].Value
Это строковая переменная. Именно поэтому когда мы туда что-то кладем, мы заключаем это в двойные кавычки. Что если нам надо положить число? Вот так мы получим ошибку
project.Variables["result"].Value = 123; //error
Чтобы ошибки не было, мы должны цифры заключить в двойные кавычки:
project.Variables["result"].Value = "123";
"Переменная уровня проекта" (которая на самом деле вообще не переменная, но для удобства я называю ее именно так) у нас от разработчиков команды ZennoLab. В обычном c# её нет. Её стоит использовать только тогда, когда вам надо перебросить данные между кубиками. Т.е. если у вас идет кубик c#, в котором надо сохранить какие-то данные, вы можете сохранить их вот в такую переменную. В остальных же случаях мы используем простые переменные, о которых сейчас и поговорим.
Строка (string)
Создаём (инициализируем) переменную с типом string
string myVariable;
Как видим, сначала мы указываем тип переменной, а затем даём ей имя. Имя может быть почти что любым.
После того, как мы её создали, мы можем присвоить ей какое-то значение (т.е. положим в нашу коробку какие-то данные). При повторном обращении к переменной прописывать тип не нужно, иначе будет ошибка.
C#:
//создаём переменную с именем message
string message;
/*
если сделаем так, то получим ошибку, т.к. при повторном обращении указывать тип
уже не нужно(т.е. не надо прописывать string)
string message = "положили какие-то данные";
*/
message = "положили какие-то данные";
message = "а теперь поменяли данные";
Обратите внимание, что тип string у нас представляет собой строку и его значение заключается в двойные кавычки (у других типов данных мы двойные кавычки ставить не будем).
Знак равно (=) в c# называется знаком присваивания. Как вы уже поняли, он присваивает переменным какое-то значение. Математическое же равно пишется двойным знаком равенства, т.е. ==.
Также мы можем объединить эти две строчки в одну. Т.е. при создании переменной сразу же присвоить ей значение
C#:
//создание строковой переменной с именем mySuperNameVariable (имя может быть любым)
string mySuperNameVariable;
//присваиваем переменной mySuperNameVariable значение "Вася Пупкин"
mySuperNameVariable = "Вася Пупкин";
//а теперь создадим строковую переменную с именем car и сразу же присвоим ей значение
string car = "Audi";
Нельзя создавать переменные с одинаковым именем. Т.е. если вы уже создали
string name = "Вася";
И позже в коде опять создадите переменную с тем же именем
string name = "Петя";
То получите в логе ошибку
Имена переменных не могут совпадать с зарезервированными словами (например, нельзя давать переменной имя string, ведь так уже обозначается тип), не могут начинаться с цифры и ещё что-то там. Запоминать это не надо, редактор сам подскажет вам, если вы накосячили.
Осмысленные части в имени переменной принято разделять регистром типа
string firstNameAndLastName = "Вася Пупкин";
И да, C# чувствителен к регистру, поэтому вот эти переменные – это три разных переменных:
C#:
//ошибки не будет, т.к. name и Name или naMe = это всё разные имена
string name = "Вася";
string Name = "Петя";
string naMe = "Коля";
string name = "Вася";
То вы уже не сможете засунуть туда int (число)
name = 123; //приведёт к ошибке
Переменная будет существовать только в рамках одного кубика C#. Т.е. если вы в 1-м кубике C# создадите переменную
string name = "Вася";
А затем создадите новый кубик C# и попробуете к ней обратиться, то будет ошибка, что данной переменной не существует.
Давайте пока вы не запутались ещё раз повторим. По сути вот эти две строки одинаковые
C#:
string message = "сообщение";
project.Variables["message"].Value = "сообщение";
Но к обычной переменной вы можете обращаться только в рамках того кубика, в котором она создана. Она как бы "уничтожается", когда мы переходим на новый кубик c#. К "переменной уровня проекта" же можно обращаться в любом кубике, и она сохранит то значение, которое вы ей присвоили.
Проверьте это на практике. Если мы выполним этот код
project.Variables["message"].Value = "сообщение";
То увидим, что значение изменилось
Т.е. теперь мы с вами умеем заменять кубик "обработка переменных" c# кодом
Мы можем объединить значения двух и более переменных в одну с помощью оператора +. Называется это конкатенацией.
C#:
string firstName = "Вася";
string lastName = "Пупкин";
string firstAndLastName = firstName + lastName;
project.SendInfoToLog(firstAndLastName); //получаем в логе " ВасяПупкин"
C#:
project.Variables["firstName"].Value = "Вася";
project.Variables["lastName"].Value = "Пупкин";
project.Variables["firstAndLastName"].Value = project.Variables["firstName"].Value + project.Variables["lastName"].Value;
project.SendInfoToLog(project.Variables["firstAndLastName"].Value); //получаем " ВасяПупкин"
C#:
string firstName = "Вася";
string lastName = "Пупкин";
project.Variables["firstAndLastName"].Value = firstName + lastName;
project.SendInfoToLog(project.Variables["firstAndLastName"].Value); //получаем в логе " ВасяПупкин"
Также вы наверное обратили внимание, что имя и фамилия у нас "слиплись". А как же добавить пробел?
C#:
string firstName = "Вася";
string lastName = "Пупкин";
string firstAndLastName = firstName + " " + lastName + " Андреевич";
project.SendInfoToLog(firstAndLastName); //получаем "Вася Пупкин Андреевич"
Числовые типы
Итак, смотрите.
double, float, decimal – это всё дроби. Пример написания:
C#:
double chislo = 2.23;
float chislo2 = 2.23f;
decimal chislo3 = 2.23m;
В основном вы будете пользоваться double. Decimal используется для операций, где важна точность, т.к. в C# (да и не только в нём) при сложении, вычитании, делении и т.д. может теряться точность в копейках.
int, uint, byte, sbyte, short, ushort, long, ulong – просто числа (без дроби). Пример написания:
C#:
int chislo4 = 25;
byte chislo5 = 3;
Полную таблицу размеров можно загуглить. Нам в принципе всё равно, мы используем int, который принимает значения что-то вроде от -2 миллиардов до 2 миллиардов и занимает 4 байта.
Но что если всё же превысить допустимый лимит? Как вы уже наверное догадались, будет ошибка
А сможем ли мы вывести наше число в лог? Давайте попробуем
Как видим, мы получим ошибку. Почему? Метод SendInfoToLog() в качестве параметра принимает у нас только string. При попытке передать любой другой тип мы получаем ошибку. Здесь нужно выполнить преобразование из int в string, но об этом чуть позже. Пока же лишь упомяну, чтобы не было ошибки, мы будем вызывать метод Convert.ToString().
Операции с числами
Плюс, минус, умножить, поделить, остаток от деления, больше, меньше, равно – всё как в математике. Единственное, равно мы пишем вот так:
==
Главное следите, чтобы числа были одного типа.
C#:
int chislo = 2;
int chislo2 = 255;
int result = chislo + chislo2;
project.SendInfoToLog(Convert.ToString(result));
C#:
string chislo = "2";
string chislo2 = "255";
string result = chislo + chislo2;
project.SendInfoToLog(result); //результат: 2255
+= означает прибавить к текущему значению
C#:
int chislo = 100;
chislo += 50; //тоже самое, что chislo = chislo + 50;
project.SendInfoToLog(Convert.ToString(chislo)); //результат: 150
! (воскл знак) означает не.
++ означает увеличить значение на один. Называется инкремент
C#:
int chislo = 0;
chislo++;
project.SendInfoToLog(Convert.ToString(chislo)); //получим 1
Можно и уменьшать на 1, используя --
C#:
int chislo = 0;
++chislo;
Boolean
Тип bool принимает два значения: true (правда) или false (ложь). Возвращается оно, когда мы проверяем какое-то условие. Например, существует ли элемент, является ли элемент таким-то и т.д.
Несколько примеров:
C#:
int chislo = 50;
int chislo2 = 100;
bool result = chislo == chislo2;
project.SendInfoToLog(Convert.ToString(result)); //т.к. значения переменных не равны, нам вернётся False
C#:
int chislo = 50;
int chislo2 = 100;
bool result = chislo < chislo2;
project.SendInfoToLog(Convert.ToString(result)); //т.к. 50 действительно меньше чем 100, нам вернется True
C#:
//вспоминаем, что воскл знак означает "не"
int chislo = 50;
int chislo2 = 100;
bool result = chislo != chislo2;
project.SendInfoToLog(Convert.ToString(result)); //т.к. 50 действительно не равно 100, нам вернется True
Char
char нужен для хранения одного символа. Пишется в одинарных кавычках. Пример:
C#:
char symb = '5';
project.SendInfoToLog(Convert.ToString(symb));
Преобразование типов
Мы можем преобразовывать один тип в другой. Для этого нужно пользоваться специальными методами. Например, с помощью метода Convert.ToString() можно преобразовать в строку (любой простой тип). Давайте попробуем
C#:
int chislo = 555;
string strChislo = Convert.ToString(chislo);
project.SendInfoToLog(strChislo); //в лог выводится, ошибок нет, значит всё получилось
C#:
bool variable = true;
string str = Convert.ToString(variable);
project.SendInfoToLog(str);
C#:
char symb = 'a';
string stroka = Convert.ToString(symb);
project.SendInfoToLog(stroka);
Аналогичные методы есть и для других типов. Я их перечислю, но вы можете и сами увидеть их, если обратите внимание на подсказку редактора
C#:
string strChislo = "123";
int chislo = Convert.ToInt32(strChislo); //для преобразования в int
string strBool = "true";
bool bl = Convert.ToBoolean(strBool); //для преобразования в bool
string strDouble = "2.01";
double d = Convert.ToDouble(strDouble); //для преобразования в double
Ну это основные. Разные short, byte и т.д. пропустим, но эти там тоже все есть.
#3
Продолжим разбираться с классами. Мы уже с вами познакомились с несколькими классами, такими как instance, tab, htmlelement и др.
Все эти классы были сделаны разработчиками ZennoPoster. Именно поэтому спрашивать о них бесполезно на форумах или у chatGpt (если только предварительно не скормить ему справку). Информацию о них нужно искать на форуме zennolab.com или в самой документации (https://help.zennolab.com/en/v7/zennoposter/7.1.4/webframe.html#topic1.html). Для этого в яндексе/гуле пишем что-то вроде «instance.SetwindowSize что делает site:zennolab.com» и читаем.
Однако помимо того, что нам предоставляют разработчики ZennoPoster, внутри самого C# (т.е. в .Net) есть масса собственных классов. Плюс есть масса библиотек, созданных сторонними разработчиками. Плюс вы можете создавать и свои собственные классы. Всё это мы будем изучать позже.
Параметры методов
Опять же для простоты условимся, что аргументы = параметры. Дело в том, что в некоторые методы мы должны передавать аргументы, чтобы они работали, а в некоторые нет. Что это такое? Легче всего объяснить на практике.
instance.ClearProxy();
Этот метод очищает прокси браузера. Видите пустые скобки? Значит данный метод не имеет никаких параметров (аргументов). А теперь посмотрим на метод с параметрами.
instance.SetProxy("127.0.0.1:8888");
https://help.zennolab.com/en/v7/zennoposter/7.1.4/webframe.html#topic377.html
Этот метод устанавливает прокси в браузер. Видите, в скобках мы прописали наш прокси? Это и есть параметр.
Значит запоминаем. Некоторые методы не требуют параметров, а некоторые требуют. Как узнать надо ли их передавать? Можно посмотреть документацию к методу (выше давал ссылки), а можно посмотреть и в самом Project Maker при написании кода. Подсказка появится после того, как вы поставите скобку.
===
Обратите внимание, что параметры перечислены через запятую. Сначала указывается тип параметра, а затем его имя (которое может быть любым и не играет роли, это имя просто подсказывает нам, что мы должны прописать).
Если мы возьмём метод SetProxy() (смотри скрин выше), то мы видим, что первым параметром передаем string (вспоминаем прошлый урок), затем bool, bool, bool. Пример:
instance.SetProxy("127.0.0.1:8888", false, true, true, true);
Также увидеть есть ли параметры у метода можно при выборе метода. Когда мы с вами пишем instance и ставим точку, то у нас появляется набор свойств и методов класса instance. Там же дается информация о том, что делает метод (на англ) и имеет ли он параметры.
Обязательные и необязательные параметры
Методы могут иметь как обязательные, так и необязательные параметры. Что это значит? Если параметр обязательный, а мы его не передали (не прописали), то будет ошибка. Если же параметр необязательный, то мы сможем запустить метод и без него. Например, вышеупомянутый метод
instance.SetProxy("…");
Имеет один обязательный (прокси) и четыре необязательных параметра (использовать ли проксифаер, устанавливать ли таймзону, гео, webrtc). Т.е. первый мы обязаны прописать в любом случае, а остальные по желанию. Понять сколько у метода обязательных параметров можно посмотрев на подсказку. Все необязательные параметры заключены в квадратные скобки.
Рассмотрим ещё один пример
instance.ClearCookie();
Данный метод очищает куки в браузере. У него 1 необязательный параметр. При желании мы можем указать те домены, для которых хотим очистить куки.
Необязательные параметры имеют значение по умолчанию. Т.е. если вы ничего не указали, то подставляется то значение, которое решили разработчики. Что это за значение смотрим в документации.
Перегрузки метода
Один и тот же метод может иметь несколько перегрузок. Это означает, что у нас есть несколько возможностей передать параметры.
Вернёмся к нашему методу по установке прокси. Когда мы его прописываем, то в подсказке видим, что он имеет три перегрузки:
Пощёлкайте по стрелкам, и вы увидите, как будут меняться тип и количество передаваемых параметров. В первой перегрузке мы должны обязательно прописать наш прокси в string и четыре по желанию в bool. Теперь нажмем на стрелку и посмотрим вторую перегрузку:
Здесь у нас уже два параметра, при этом первый имеет тип ProxySettings, а второй NetworkSettings. Они оба обязательные.
Нажмём на стрелку ещё раз и увидим третью перегрузку:
Ага, тут у нас уже три обязательных параметра (сразу смотрим на типы, это string-int-string) и 6 необязательных.
Давайте вспомним метод из предыдущего пункта Convert.ToString()
Как видим, у него вообще 36 перегрузок. Именно поэтому у нас в качестве параметра может быть как int, так и bool, char, uint и многие другие типы.
Тип передаваемых параметров
Прежде чем прописывать какой-то из параметров, нам надо посмотреть на его тип. Обычно это простые типы, пройденные нами в предыдущем уроке (string, int, bool и т.д.), но необязательно.
Посмотрим на вторую перегрузку этого метода ещё раз
Мы видим, что тут в качестве 1-го параметра идёт "сложный" тип данных ProxySettings, а в качестве 2-го NetworkSettings.
Соответственно, прежде чем мы сможем их прописать, нам надо будет разобраться, что это за типы и как с ними работать (читаем справку, форум зенно, гугл, chatGpt). Далее их создать, заполнить и затем уже передать.
Возвращаемый тип данных
Методы могут не просто что-то делать, но и что-то возвращать. А возвращать они опять же будут какой-то тип данных (class, если вам так проще). Это мы можем увидеть в подсказке, либо в документации. Давайте вернемся к уже ставшему нами любимому методу по установке прокси. Глядите сюда
void означает, что метод ничего не возвращает. Значит, он просто что-то делает и на этом всё.
А теперь посмотрим на другой метод
instance.GetCookie();
Видим, что данный метод возвращает string (значит результат его работы надо положить в переменную с типом string).
C#:
string myCookieBrowser = instance.GetCookie();
return myCookieBrowser;
instance.GetCookie();
Просто конкретно в данном случае мы не увидим результат работы метода, т.к. его единственным предназначением является возврат кук.
Как и в случае с параметрами возвращаемый тип данных необязательно будет простым. Например вот тут
Нам вернётся массив IExtension. Т.е. разбираемся, что это, создаем, потом уже присваиваем ей результат работы метода.
#4
Условия if
Условия if
В любой программе условия используются постоянно. "Если переменная равна тому-то, то делай это", "Если элемент не найден, делай вот это" и т.д. Условие прописывается следующим образом
C#:
int age = 18;
if(age == 18)
{
project.SendInfoToLog("age действительно 18");
}
- Первой строкой мы объявили переменную типа int с именем age и присвоили ей значение 18
- Второй строкой мы говорим "если age равна 18, то выполни то, что находится внутри {}. В данном случае выведи сообщение в лог".
Мы также можем прописать, что делать если условие НЕ выполнено.
C#:
int age = 11;
if(age == 18)
{
project.SendInfoToLog("age действительно 18");
}
else
{
project.SendInfoToLog("age не равна 18. она равна " + Convert.ToString(age));
}
Ладно, что-то я отвлекаюсь. Всё равно на текст наверное оно не очень воспринимается, на практике ещё закрепим. А пока продолжим.
Мы также можем прописать несколько различных условий, используя else if. Т.е. у нас будет если age == 18, делай то-то, если она равна 20, то делай то-то, если 30, то делай то-то, а если ничему из этого, то делай вот это.
C#:
int age = 20;
if(age == 18)
{
project.SendInfoToLog("age действительно 18");
}
else if(age == 20)
{
project.SendInfoToLog("age равна 20");
}
else if(age == 20)
{
project.SendInfoToLog("age равна 20");
}
else if(age == 30)
{
project.SendInfoToLog("age равна 30");
}
else
{
project.SendInfoToLog("age равна " + Convert.ToString(age));
}
Помимо знака равно, мы можем использовать и другие, такие как не равно != больше или меньше > <, >= <=.
C#:
int age = 20;
//обратите внимание, что выполнится только первое условие, остальные опустятся
if(age != 18)
{
project.SendInfoToLog("age действительно НЕ РАВНА 18");
}
else if(age == 20)
{
project.SendInfoToLog("age равна 20");
}
else if(age == 20)
{
project.SendInfoToLog("age равна 20");
}
else if(age == 30)
{
project.SendInfoToLog("age равна 30");
}
else
{
project.SendInfoToLog("age равна " + Convert.ToString(age));
}
C#:
int age = 10;
if(age >= 18)
{
project.SendInfoToLog("age действительно НЕ РАВНА 18");
}
else if(age == 20)
{
project.SendInfoToLog("age равна 20");
}
else if(age < 18)
{
project.SendInfoToLog("age равна 20");
}
C#:
string message ="hello world";
bool flag = true;
if(message == "hello world")
{
project.SendInfoToLog("message у нас hello world");
}
if(flag == true)
{
project.SendInfoToLog("flag true");
}
Если у вас то, что в {} занимает только одну строку, их можно не прописывать
C#:
bool flag = true;
if(flag == true) project.SendInfoToLog("можно так");
if(flag == true)
project.SendInfoToLog("так тоже можно с переносом на след строку");
Когда у нас в скобках идёт bool, можно прописывать сокращенно
C#:
bool flag = true;
//тоже самое что if(flag == true)
if(flag) project.SendInfoToLog("оки");
//тоже самое что if(flag == false)
if(!flag) project.SendInfoToLog("no");
Использование "и" и "или" в условиях
Мы можем проверять сразу несколько утверждений. С помощью && задается "и", а с помощью || "или".
C#:
string str = "message";
bool flag = true;
if(str == "message" && flag == true)
{
project.SendInfoToLog("оба условия выполнены");
}
C#:
string str = "message";
bool flag = true;
if(str == "message" || flag == true)
{
project.SendInfoToLog("оба условия выполнены");
}
C#:
string str = "message";
bool flag = true;
if(str == "message" ^ flag == false)
{
project.SendInfoToLog("оба условия выполнены");
}
Видимость переменных
Переменная, объявленная внутри фигурных скобок {}, будет видна только там. Давайте разберемся на практике
Мы получаем ошибку, код даже не запустится. Посмотрите на описание "The name 'test' does not exist in the current context". [Строка: 9; Cтолбец: 23]" (имя test не существует в данном контексте).
К слову, нумерацию строк мы можем вкл щёлкнув правой кнопкой мыши по полю, где пишем код и выбрав "нумерация строк"
Также можно вкл в настройках по умолчанию
Итак, вернёмся к нашей ошибке. Т.к. переменная test была создана внутри {}, то и использовать её можно только там. За пределами её уже нет. Чтобы она была видна за фигурными скобками, надо было её создать до них
C#:
string message ="hello world";
string test = "тестируем видимость переменнной";
if(message == "hello world")
{
project.SendInfoToLog(test);
}
project.SendInfoToLog(test);
Переменная будет видна только в рамках одного кубика C#. Смотрите, я создал два кубика
В "кубике 1" я прописал следующую строчку
string message ="hello world";
Если я теперь попробую в "кубике 2" к ней обратиться, то получу ошибку "переменная message не существует в данном контексте"
В "кубике 2" уже можно заново создавать переменные с теми же именами. Т.е. если у вас в "кубике 1" есть переменная с именем message, то в "кубике 2" тоже можно её создавать, никакой ошибки не будет
Я уже кажется об этом упоминал, но скажу ещё раз. Перекинуть значение переменных из одного кубика в другой можно с помощью "переменных уровня проекта". Они будут существовать во всех кубиках. Они имеют тип string.
В [""] указывается имя переменной. Не забудьте только создать её вручную, как вы это раньше всегда делали.
Чтобы постоянно не прописывать эту длинную строку, вы можете нажать правой кнопкой мыши по редактору кода и выбрать там из списка.
Видео по теме - youtube.com/watch?v=EpTRp6deeYI
Списки
У нас есть списки из .Net и списки, созданные разработчиками ZennoPoster. Работают они на 99% одинаково.
Давайте для простоты начнём с зенковского списка. Доступны те же операции, что и в кубике "Операции над списком" – добавление в список, удаление и т.д.
Все строки внутри этого списка имеют тип string.
Первым делом создаём его вручную
Теперь получим к нему доступ
IZennoList list = project.Lists["Список 1"];
- Список 1 – это то имя, которое вы задавали, когда создавали список.
- list – это имя переменной с типом IZennoList. Оно может быть любым
- Add() – добавляет строку в список
- AddRange() – добавляет данные из другого списка
- Bind() – привязка файла к списку, если вы это не делали вручную при его создании
- Clear() – очищает список
- Contains() – проверяет наличие строки в списке (полное совпадение). Возвращает bool
- Count – это свойство. Возвращает количество элементов в списке
- Insert() – позволяет вставить строку в определенное место в списке (куда-то в середину, например)
- Remove() – удаляет строку по значению
- RemoveAt() – удаляет строку по номеру (счёт с нуля)
C#:
//инициализируем список
IZennoList list = project.Lists["Список 1"];
//очищаем список
list.Clear();
//добавляем элементы в список
list.Add("Вася");
list.Add("Петя");
list.Add("Коля");
//выводим в лог первый элемент списка
string firstStr = list[0];
project.SendInfoToLog(firstStr);
//проверяем наличие в списке
bool checkPety = list.Contains("Петя");
if(checkPety == true)
{
project.SendInfoToLog("петя есть в списке");
}
//удаляем первый элемент из списка и потом выводим первый элемент в лог
list.RemoveAt(0);
firstStr = list[0];
project.SendInfoToLog(firstStr);
//получаем количество строк в списке
int countList = list.Count;
project.SendInfoToLog("В списке столько строк - " + Convert.ToString(countList));
Теперь про списки, которые находятся внутри .Net. Это своего рода "виртуальный" список, который будет жить в рамках одного кубика. Аналогию можно провести с переменными. Т.е. если мы берём переменную
project.Variables["number"].Value = "";
То она живёт на протяжении всего проекта в любых кубиках c#. Если же мы берём такую переменную
string message = "";
То она будет существовать только в рамках кубика, где была создана.
Аналогично с нашими списками. Если мы возьмём список IZennoList, то он тоже живёт на протяжении всего проекта. Если же мы берем "виртуальный" список, то он живёт в рамках одного кубика c#. Создаётся он так
List<string> myName = new List<string>();
P.S. myName – это имя, может быть любым.
И далее для него актуальны всё те же методы, что мы прошли для IZennoList.
Зачем он тогда нужен вообще, если данные на пк не сохраняются? Ну например, вы что-то спарсили со страницы в этот список, затем обработали каким-то образом, а потом уже сохраняете на пк с помощью метода File.ReadAllLines(). Этот метод пройдём позже. Плюс тут мы можем использовать не только тип string, но и любые другие, как простые (int, bool, char и т.д.), так и сложные (HtmlElement, mHatch и др.).
Также здесь есть несколько дополнительных методов:
- Shuffle() – перемешивает элементы списка
- Sort() – сортирует список
C#:
List<string> myName = new List<string>();
//добавляем элементы в список
myName.Add("Вася");
myName.Add("Петя");
myName.Add("Коля");
myName.Add("Катя");
myName.Add("Надя");
myName.Add("Лена");
//выводим в лог первый элемент списка
string firstStr = myName[0];
project.SendInfoToLog(firstStr);
//проверяем наличие в списке
bool checkPety = myName.Contains("Петя");
if(checkPety == true)
{
project.SendInfoToLog("петя есть в списке");
}
//удаляем первый элемент из списка и потом выводим первый элемент в лог
myName.RemoveAt(0);
project.SendInfoToLog(myName[0]);
//получаем количество строк в списке
int countList = myName.Count;
project.SendInfoToLog("В списке столько строк - " + Convert.ToString(countList));
//перемешиваем список и выводим в лог 1-й элемент
myName.Shuffle();
project.SendInfoToLog(myName[0]);
//сортируем список по алфавиту и выводим в лог 1-й элемент
myName.Sort();
project.SendInfoToLog(myName[0]);
Циклы
Циклы нужны для совершения повторяющихся действий. Например, это может быть перебор списка, перебор элементов на странице и т.д. В C# есть циклы for, while, do-while, foreach. Мы рассмотрим только for, чтобы не забивать голову лишним. Без остальных можно жить, но мы всё равно вернёмся к ним позже.
Мы помним, что в списке элементы получаются по индексу
list[0] – первый элемент
list[1] – второй элемент
и т.д. Смысл цикла в том, что вместо указания прямого индекса мы будем подставлять переменную, которая каждый круг будет увеличиваться.
C#:
List<string> myName = new List<string>();
//добавляем элементы в список
myName.Add("Вася");
myName.Add("Петя");
myName.Add("Коля");
myName.Add("Катя");
myName.Add("Надя");
myName.Add("Лена");
//получим кол-во элементов
int count = myName.Count;
int i=0;
//перебираем список
for(i=0;i<count;i = i+1)
{
string el = myName[i];
project.SendInfoToLog(el);
}
project.SendInfoToLog("================");
//перемешаем список
myName.Shuffle();
//переберем ещё раз, используя более короткую запись
for(int j=0;j<myName.Count;j++)
{
project.SendInfoToLog(myName[j]);
}
C#:
List<string> myName = new List<string>();
//добавляем элементы в список
myName.Add("Вася");
myName.Add("Петя");
myName.Add("Коля");
myName.Add("Вася");
myName.Add("Вася");
myName.Add("Вася");
myName.Add("Катя");
myName.Add("Надя");
myName.Add("Лена");
myName.Add("Вася Пупкин");
myName.Add("Вася Иванов");
myName.Add("Иванов Вася");
int sch = 0;
for(int i=0;i<myName.Count;i++)
{
bool checkName = myName[i].Contains("Вася");
if(checkName == true)
{
continue;
}
sch = sch + 1;
project.SendInfoToLog(myName[i]);
}
project.SendInfoToLog("Количество строк, в которых нет слова Вася - " + Convert.ToString(sch));
C#:
List<string> myName = new List<string>();
//добавляем элементы в список
myName.Add("Вася");
myName.Add("Петя");
myName.Add("Коля");
myName.Add("Вася");
myName.Add("Вася");
myName.Add("Вася");
myName.Add("Катя");
myName.Add("Надя");
myName.Add("Лена");
myName.Add("Вася Пупкин");
myName.Add("Вася Иванов");
myName.Add("Иванов Вася");
string name = "";
bool flag = false;
for(int i=0;i<myName.Count;i++)
{
bool checkName = myName[i] == "Надя";
if(checkName == true)
{
flag = true;
name = myName[i];
break;
}
}
if(flag == true)
{
project.SendInfoToLog("нашли Надю и положили её в переменную name - " + name);
}
else
{
project.SendInfoToLog("Нади не было в списке");
}
Циклы можно вкладывать "один в другой" (вложенные циклы). Только имя счётчика меняйте.
P.S. Счётчиком называют переменную, с которой начинается цикл. В нашем случае это было int i=0.
Нормальный пример сходу придумать не получается, поэтому просто бредовый приведу вам. На практике ещё встретим такую ситуацию, я думаю.
C#:
List<string> myName = new List<string>();
//добавляем элементы в список
myName.Add("Вася");
myName.Add("Петя");
myName.Add("Коля");
myName.Add("Вася");
myName.Add("Вася");
myName.Add("Вася");
myName.Add("Катя");
myName.Add("Надя");
myName.Add("Лена");
myName.Add("Вася Пупкин");
myName.Add("Вася Иванов");
myName.Add("Иванов Вася");
string name = "";
bool flag = false;
for(int i=0;i<myName.Count;i++)
{
bool checkName = myName[i] == "Надя";
if(checkName == true)
{
flag=true;
name = myName[i];
for(int j=0;j<10;j++)
{
project.SendInfoToLog("надю нашли. наш j на текущий момент - " + Convert.ToString(j));
}
}
}
if(flag == true)
{
project.SendInfoToLog("нашли Надю и положили её в переменную name - " + name);
}
else
{
project.SendInfoToLog("Нади не было в списке");
}
Видео по теме -
Генерация своей ошибки
Мы можем сгенерировать собственную ошибку. Зачем это надо? Например, если какой-то элемент не найден, то возможно нам нет смысла продолжать выполнять наш проект. Для этого генерируем ошибку и идем по красной ветке. При этом в логе будет нормальное описание и номер строки, где была сгенерирована ошибка.
C#:
project.SendInfoToLog("вывод в лог №1");
throw new Exception("моя собственная ошибка");
project.SendInfoToLog("вывод в лог №2");
Поиск ошибок
В будущем в вашем проекте у вас может быть множество кубиков C#. Имейте ввиду, что ошибка в одном кубике приводит к тому, что все кубики C# перестают работать. Если возникает ошибка первым делом надо определить, в каком именно кубике C# она возникла. Делается это также, как с обычными кубиками.
Давайте создадим несколько кубиков и умышленно забудем поставить точку с запятой в одном из них
Идём в лог -> жмём правой кнопкой мыши по ошибке -> скопировать айди действия
Идём в "редактирование" -> "поиск по проекту" (или жмём "ctrl F")
Вставляем айди и жмём найти. Мы попадём на кубик с ошибкой
В логе мы видим на какой именно строке ошибка и её описание. Иногда он может косячить и незначительно ошибаться с номером строки
Иногда номер строки не отображается вовсе. Как в таком случае понять, где ошибка? Обычно, когда это случается, он вам позволит запустить кубик. А ошибка возникнет по ходу выполнения. В этом случае можно выполнить код пошагово. Для этого жмём сюда и у вас появляется красный кружок
Теперь запускаем кубик и выполняем код построчно
Так вы сможете дойти до ошибки.
Ещё один вариант – натыкать выводов в лог и посмотреть, какой именно не выведется.
try-catch
Если мы знаем, что в каком-то месте кода может произойти ошибка, и мы хотим её обработать, мы можем использовать специальную конструкцию try-catch.
C#:
try
{
project.SendInfoToLog("псевдокод");
//тут 100500 строк кода
throw new Exception("вдруг где-то возникла ошибка");
}
catch(Exception e)
{
project.SendInfoToLog("Описание ошибки" - e.Message);
}
finally
{
project.SendInfoToLog("я выполнюсь в любом случае");
}
Если ошибка действительно возникает, выполнение перескакивает в блок catch {} и выполняется код, написанный там.
Если ошибка НЕ возникает, то выполнится только то, что внутри try {}. То, что в catch {}, выполняться не будет.
finally {} выполнится в любом случае, независимо от того, попали мы в catch или нет. finally можно не прописывать вовсе, если он вам не нужен.
Быстрое создание переменных одного типа
Если вам нужно объявить несколько переменных одного типа их можно перечислить через запятую:
C#:
string firstname = "Вася", lastname = "Иванов", job = "Сантехник";
project.SendInfoToLog(firstname);
Интерполяция строк
Ранее мы с вами соединяли строки с помощью оператора +, например:
C#:
string firstname = "Вася", lastname = "Иванов", job = "Сантехник";
string fullInformation = firstname + " " + lastname + " " + job;
project.SendInfoToLog(fullInformation);
C#:
string firstname = "Вася", lastname = "Иванов", job = "Сантехник";
string fullInformation = $"наш рабочий это: {firstname} {lastname}. Его специализация {job}";
project.SendInfoToLog(fullInformation);
Константы
Мы можем запретить изменять значение переменной, прописав слово const.
const string name = "вася";
Такая переменная называется константой. При попытке поменять значение получаем ошибку
#5
lock
lock
Когда мы пишем код на C#, мы должны с вами сами контролировать, чтобы разные потоки не могли одновременно обратиться к одному и тому же файлу, иначе можно получить ошибку (вы же не хотите, чтобы одна и та же почта из файла попала сразу к двум-трём потокам?). Это может быть список, таблица, база данных. Для этого существует конструкция lock.
Суть её очень простая. Если какой-то из потоков зашёл внутрь lock {}, то пока он оттуда не выйдет, другие должны будут ждать.
Как это можно написать
C#:
IZennoList list = project.Lists["Список 1"];
lock(SyncObjects.ListSyncer)
{
//обращение к списку, таблице, бд
string str = list[0];
list.RemoveAt(0);
}
- SyncObjects.ListSyncer – для списков
- SyncObjects.TableSyncer – для таблиц
- SyncObjects.InputSyncer – для буфера обмена
- SyncObject – общее
Мы также можем создавать и свои объекты для лока. Для этого создаем общий код
И на 33-й строке мы уже видим одну из наших заготовок
По образу и подобию создаём свои, меняем только имя (SyncObject)
И теперь можем их использовать в кубике c#, обращаясь таким образом: имя_класса.имя_объекта
C#:
lock(CommonCode.OneLock)
{
//обращение к списку, таблице, бд
string str = list[0];
//list.RemoveAt(0);
}
Дело в том, что один такой лок
C#:
lock(CommonCode.OneLock)
{
}
Соответственно, если вы будете использовать какой-то один объект для всех файлов (например тот, что мы написали выше), то при работе в множество потоков у вас может возникнуть нехилая такая "пробка" – очередь из потоков.
Поэтому будет неплохо для каждого файла создавать свой объект для лока. Например, у вас есть файл с прокси. Создайте для него
public static object ProxyLock = new object();
И используйте его. Для файла с ключевыми словами создайте новый
public static object KeyLock = new object();
И используйте его
C#:
lock(CommonCode.KeyLock)
{
string str = list[0];
}
Работа с таблицами
По тому же принципу, что мы работали со списками, используя IZennoList, мы можем работать с таблицами. Т.е. первым делом вручную создаем таблицу, даём ей имя и привязываем к файлу. Потом работаем с кодом.
Инициализация
IZennoTable table = project.Tables["Таблица 1"];
Добавление строк
C#:
table.ColSeparator = ";"; //задаём разделитель столбцов
string str1 = "вася;пупкин;сантехник"; //добавляемая строка
string str2 = "петя;пчелкин;электрик";
string str3 = "гена;букин;продавец обуви";
table.AddRow(str1);
table.AddRow(str2);
table.AddRow(str3);
C#:
string str = table.GetCell(0, 0); //первая колонка первый столбец (счёт с нуля)
project.SendInfoToLog(str);
table.SetCell(0, 0, "Жора"); //первая строка первый столбец установим "Жора"
Удаляем колонку
table.DeleteColumn(2); //удаляем третью колонку (счёт с нуля)
Удаляем строку
table.DeleteRow(0); //удаляем первую строку
Получаем количество колонок и строк
C#:
int colCount = table.ColCount; //кол-во колонок
int rowCount = table.RowCount; //кол-во строк
C#:
List<string> list = table.GetRow(0).ToList(); //получаем первую строку
for(int i=0;i<list.Count;i++)
{
project.SendInfoToLog(list[i]);
}
table.Clear();
Массивы
Массивы – тоже самое что списки, только имеют они строго определенную длину. Т.е. если мы создали массив из 5 элементов, то изменить это количество мы уже не сможем.
Инициализация массива:
C#:
int[] mass = new int[4];
mass[0] = 12;
mass[1] = 55;
mass[2] = 33;
mass[3] = 23;
int[] mass = new int[] {124,12412,21,57,89};
Используемый тип может быть любым. Хоть string, хоть HtmlElement (и т.д.).
Получение длины массива происходит с помощью свойства Length (не Count как у списков)
int longMass = mass.Length;
Перебор в цикле аналогичен перебору списков
C#:
int[] mass = new int[] {124,12412,21,57,89};
for(int i=0;i<mass.Length;i++)
{
project.SendInfoToLog(Convert.ToString(mass[i]));
}
int m = mass[0]; //получим первый элемент
Словарь (Dictionary)
Словарь – это коллекция, позволяющая нам хранить данные в формате "ключ значение".
Инициализируем словарь и добавляем значения
C#:
Dictionary<string, string> sl = new Dictionary<string, string>();
sl.Add("Имя", "Вася"); //сначала ключ, потом значение
sl.Add("Фамилия", "Иванов");
Обращение к элементу происходит по ключу, а получаем мы значение этого ключа
C#:
Dictionary<string, string> sl = new Dictionary<string, string>();
sl.Add("Имя", "Вася");
sl.Add("Фамилия", "Иванов");
string str = sl["Фамилия"];
project.SendInfoToLog(str); //Результат: Иванов
sl.Clear();
Проверка наличия ключа
C#:
Dictionary<string, string> sl = new Dictionary<string, string>();
sl.Add("Имя", "Вася");
sl.Add("Фамилия", "Иванов")
bool checkName = sl.ContainsKey("Имя");
return checkName; //True
C#:
Dictionary<string, string> sl = new Dictionary<string, string>();
sl.Add("Имя", "Вася");
sl.Add("Фамилия", "Иванов");
bool checkName = sl.ContainsValue("Василий");
return checkName; //False
int count = sl.Count;
Пример перебора словаря
C#:
Dictionary<string, string> sl = new Dictionary<string, string>();
sl.Add("Имя", "Вася");
sl.Add("Фамилия", "Иванов");
for(int i=0;i<sl.Count;i++)
{
string key = sl.ElementAt(i).Key;
string value = sl.ElementAt(i).Value;
project.SendInfoToLog($"Ключ: {key}. Значение: {value}");
}
Var
Когда мы используем var, мы говорим компилятору, чтобы он сам подставил тип переменной. Он смотрит на "правую" часть (какой тип там находится) и исходя из этого определяет тип переменной. Примеры
C#:
var str = "строка"; //это у нас будет string
var number = 123; //это будет int
var tab = instance.ActiveTab; //а это Tab
var el = tab.FindElementByXPath("//p", 0); //это HtmlElement
Object
object является базовым для всех типов данных.
Так как все классы в .NET являются производными Object, каждый метод, определенный в Object классе, доступен во всех объектах в системе. Производные классы могут переопределять некоторые из этих методов, включая:
- Equals: поддерживает сравнения между объектами.
- Finalize: выполняет операции очистки перед автоматическим восстановлением объекта.
- GetHashCode: создает число, соответствующее значению объекта для поддержки использования хэш-таблицы.
- ToString: производит текстовую строку, читаемую человеком, которая описывает экземпляр класса.
C#:
object str = "строка";
//str = str.Replace("строка", "123"); - будет ошибка, мы не можем пользоваться методами для string если у нас переменная object
object number = 123;
return str;
Dynamic
dynamic позволяет нам создавать переменную с любым типом. Ключевым тут является то, что это ключевое слово опускает проверку типов во время компиляции. Лучше не использовать и вот почему:
- У вас не будет подсказок во время написания кода
- Узнать об ошибке вы сможете только после запуска кода
C#:
dynamic str = "строка";
str = str.Replace("строка", "123");
dynamic number = 123;
Методы string
Мы рассмотрим наиболее популярные свойства и методы. Это во многом аналогично вот этому кубику
Все нижеизложенные примеры мы ещё раз посмотрим в видео и также вы найдёте их в шаблоне "4".
Замена
Для этого используем метод Replace(). В качестве 1-го параметра передается старое значение, а в качестве 2-го новое
C#:
//создадим переменную с именем text и присвоим ей значение
string text = "Вася пошёл на прогулку и вернулся только в 20:00";
//выведем в лог значение
project.SendInfoToLog(text);
//заменим фразу "на прогулку" на "гулять" и выведем в лог
string newText = text.Replace("на прогулку", "гулять");
project.SendInfoToLog(newText);
//сохраним новое значение в переменной уровня проекта "name"
project.Variables["name"].Value = newText;
Делается методами toUpperCase() и toLowerCase().
C#:
//создадим новую переменную с именем "toUpperVariable" и переведем в верхний регистр и выведем в лог
string toUpperVariable = text.ToUpper();
project.SendInfoToLog(toUpperVariable);
//а теперь в нижний регистр
string toLowerVariable = text.ToLower();
project.SendInfoToLog(toLowerVariable);
С помощью метода Contains() мы можем проверить, есть ли в нашей переменной нужное слово. Обратите внимание, что метод возвращает тип bool, а значит и результат мы должны положить в переменную с типом bool. Но вот незадача. Чтобы вывести результат в лог (с помощью project.SendInfoToLog()) мы должны передать string, а не bool. Что же делать? Нужно превратить bool в string и только потом выводить в лог. Не переживайте, эту тему мы ещё затронем позже
C#:
bool checkText = text.Contains("Вася");
string checkTextToString = Convert.ToString(checkText);
project.SendInfoToLog(checkTextToString);
Метод Count() позволяет нам посчитать количество символов в тексте. Также можно это сделать и с помощью свойства Length. Обратите внимание, что этот метод возвращает уже int, а значит и результат мы ложим в переменную с типом int. Ну, а далее чтобы вывести в лог или сохранить результат в переменную уровня проекта, нам надо превратить int в string аналогично тому, как делали выше
C#:
//узнаём количество символов в тексте с помощью Count и выводим в лог
int countSymbolsInText = text.Count();
string strCountSymbolInText = Convert.ToString(countSymbolsInText);
project.SendInfoToLog(strCountSymbolInText);
//узнаём количество символов в тексте и выводим в лог с помощью свойства Length
int countSymbolsInTextLengthProperties = text.Length;
string strCountSymbolInTextLengthProperties = Convert.ToString(countSymbolsInTextLengthProperties);
project.SendInfoToLog(strCountSymbolInTextLengthProperties);
Метод StartsWith() позволяет проверить, начинается ли строка с нужной фразы. Метод EndsWith() проверяет, заканчивается ли строка указанный нами фразой. Оба метода в результате выполнения возвращают bool
C#:
//узнаем начинается ли переменная с Вася пошёл
bool startText = text.StartsWith("Вася пошёл");
string strStartText = Convert.ToString(startText);
project.SendInfoToLog("Результат выполнения начинается ли текст с фразы 'Вася пошёл' - " + strStartText);
//узнаем заканчивается ли переменная на 20:00
bool endText = text.EndsWith("Вася пошёл");
string strEndText = Convert.ToString(endText);
project.SendInfoToLog("Результат выполнения чем заканчивается текст - " + strEndText);
Метод IndexOf() позволяет узнать, с какого символа начинается указанная нами фраза. Если её вообще нет, то вернётся -1.
C#:
//откуда начинается искомая фраза (прогулк)
int checkWalk = text.IndexOf("прогулк");
string strCheckWalk = Convert.ToString(checkWalk);
project.SendInfoToLog($"искомое слово начинается с {strCheckWalk} символа");
Вставка фразы
Метод Insert() позволяет вставить новую строку в переменную. 1-м параметром передаем с какого символа вставляем (int), а вторым саму фразу (string).
C#:
//вставляем фразу начиная с 5-го символа
string newTextAddPhrase = text.Insert(5, "Пупкин ");
project.SendInfoToLog(newTextAddPhrase);
Метод Remove() позволяет удалить часть строки. 1-м параметром передаем откуда удаляем (int), 2-м параметром сколько удаляем (int)
C#:
//удаляем часть строки
string deleteText = text.Remove(0, 4);
project.SendInfoToLog(deleteText);
Метод Trim() удалит пробелы в начале и конце строки. Метод TrimStart() удалит только в начале, а TrimEnd() только в конце.
C#:
//удаляем пробелы
string strForEdit = " строка с пробелами ";
project.SendInfoToLog("так выглядит строка с пробелами - " + strForEdit);
string newStrForEdit = strForEdit.Trim();
project.SendInfoToLog("убрали пробелы - " + newStrForEdit);
Ещё пара слов
Переменные можно объединять друг с другом с помощью оператора +. Это называют конкатенацией строк. Также можно пользоваться и другим способом, продемонстрированном ниже
C#:
//объявляем переменные
string str1 = "первая строка";
string str2 = "вторая строка";
//объединяем
string str3 = str1 + str2;
project.SendInfoToLog("результат - " + str3);
//добавим пробел
string str4 = str1 + " " + str2;
project.SendInfoToLog("добавили пробел, чтобы нормально смотрелось");
//объединяем 2-м способом
string str5 = $"ещё можно вот так соединять: {str1} {str2}";
project.SendInfoToLog(str5);
project.SendInfoToLog("пишем текст");
Можем указать переменную (но только в string)
C#:
string str = "пишем текст";
project.SendInfoToLog(str);
C#:
string str = "пишем текст";
project.SendInfoToLog(str + " добавляем что угодно".Insert(0, " И ещё добавим "));
#6
Порядок передачи параметров в методы
Порядок передачи параметров в методы
Мы с вами всегда прописывали параметры по порядку. Но на самом деле их можно указывать в любом порядке, только в таком случае нам надо прописывать имя параметра
C#:
Tab tab = instance.ActiveTab;
tab.Navigate(referrer: "google.ru", url: "ya.ru");
Цепочка вызовов
Мы можем существенно сокращать объём написания кода, используя так называемую "цепочку вызовов". Давайте я лучше объясню на примерах. Вот так мы совершаем переход на сайт
C#:
Tab tab = instance.ActiveTab;
tab.Navigate("ya.ru");
Но мы можем обращаться и сразу без создания переменной таким образом
instance.ActiveTab.Navigate("ya.ru");
Поскольку instance.ActiveTab возвращает нам объект Tab, компилятор сам понимает, что теперь он работает с Tab и предоставляет нам свойства и методы для работы с ним.
Эта цепочка может быть сколь угодно длинной
string str = instance.ActiveTab.MainDocument.FindElementByXPath("/html/body/div/div[@class]", 0).FullTagName;
- instance.ActiveTab возвращает Tab. Мы получили доступ к его свойствам и методам
- MainDocument является свойством класса Tab. Он возвращает тип Document, так что теперь мы получили доступ к нему
- У класса Document есть метод FindElementByXpath() (да, этот метод доступен не только в классе Tab, но и в классе Document) который вернул нам тип HtmlElement
- У HtmlElement есть свойство FullTagName, который возвращает тип string. Именно поэтому мы положили результат в тип string.
C#:
Tab tab = instance.ActiveTab;
Document doc = tab.MainDocument;
HtmlElement el = doc.FindElementByXPath("/html/body/div/div[@class]", 0);
string str = el.FullTagName;
Цикл While
Аналогичен циклу for, но записывается чуть иначе. Переберем список
C#:
List<string> list = new List<string>()
{
"Вася",
"Петя",
"Коля"
};
int i=0; //счётчик
while(i < list.Count)
{
project.SendInfoToLog(list[i]);
i++; //увеличение счётчика
}
Иногда while используется для создания бесконечных циклов. Только не забывайте предусмотреть выход из него, чтобы программа не зависла
C#:
List<string> list = new List<string>()
{
"Вася",
"Петя",
"Коля"
};
int i=0; //счётчик
string str = "";
while(true)
{
try {
str = list[i];
}
catch{
project.SendInfoToLog("перебрали список");
break;
}
project.SendInfoToLog(list[i]);
i++; //увеличение счётчика
}
Цикл do while
В отличии от while, тот код, что находится в do {} будет выполнен в любом случае, даже если условие в скобках ложно.
C#:
List<string> list = new List<string>()
{
"Вася",
"Петя",
"Коля"
};
int i=0; //счётчик
string str = "";
do
{
project.SendInfoToLog(list[i]);
i++; //увеличение счётчика
}
while(i < list.Count);
Цикл foreach
Удобен для перебора коллекций, но не всегда его можно использовать
C#:
List<string> list = new List<string>()
{
"Вася",
"Петя",
"Коля"
};
foreach(string s in list)
{
project.SendInfoToLog(s); //в s автоматически кладется сначала первый элемент списка, затем 2-й и т.д. пока не переберем всё
}
Условие switch
Всё, что делается на switch, можно сделать на if-else. А вот в обратную сторону это не работает. Но в некоторых случаях код читатется легче именно со switch.
C#:
List<string> list = new List<string>()
{
"Вася",
"Петя",
"Коля"
};
switch(list[0]) //тут переменная, значение которой проверяем
{
case "Вася": //тут возможное значение переменной
project.SendInfoToLog("Первый элемент в списке Вася"); //тут действия, если значение совпало. можно сколько угодно строк
break; //так мы говорим, что действия закончены
case "Петя":
project.SendInfoToLog("Первый элемент в списке Петя");
break;
case "Коля":
project.SendInfoToLog("Первый элемент в списке Коля");
break;
case "Михаил":
case "Василий":
project.SendInfoToLog("Михаил или Василий");
break;
default: //если не совпало никакое из значений
project.SendInfoToLog("первый элемент в списке неизвестен");
break;
}
#10
Введение в общий код
Для чего вам общий код
Введение в общий код
Для чего вам общий код
Давайте я сначала объясню вам чем вам может быть полезен общий код. Разберем пример клика по элементу на c# (код составлен для стр https://ya.ru/).
C#:
HtmlElement el = null;
Tab tab = instance.ActiveTab;
Random r = new Random();
for (int i = 0; i<30; i++)
{
//пробуем отыскать элемент
el = tab.FindElementByXPath("//div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]", 0);
//если найден, пауза и выходим из цикла
if (!el.IsVoid)
{
Thread.Sleep(r.Next(1000, 3000));
break;
}
//выход по ошибке, если элемент не появился
if (i == 29) throw new Exception("не дождались появления элемента //div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]");
//пауза 1 сек
project.SendInfoToLog("ждём появления элемента //div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]");
Thread.Sleep(1000);
}
//клик
tab.FullEmulationMouseMoveToHtmlElement(el);
Thread.Sleep(r.Next(300, 1000));
tab.FullEmulationMouseClick("left", "click");
//ожидание загрузки и пауза
if (tab.IsBusy) tab.WaitDownloading();
Thread.Sleep(r.Next(1000, 3000));
browser.Click(project, instance, "//div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]");
Вот именно этому мы с вами и научимся. Помимо создания своей библиотеки вы также можете выносить в общий код и логику проекта. Правда, делать это грамотно я вас научить не смогу, но понимание того, как это делается, вы получите.
Библиотеки
Откроем ссылки из GAC. Здесь мы с вами видим те пространства имен (библиотеки), что уже используются в проекте. Т.е. в данном случае у нас добавлено System, System.Core и т.д. Можно зайти на microsoft, вбить это название в поиск и ознакомиться, что там есть.
Кнопкой "удалить" можно убрать ненужные. Кнопкой "добавить" можно добавить новые. Давайте нажмём её. Тут мы с вами видим все доступные нам библиотеки (1), их версию (2) и путь к ним (3)
Чтобы в ваш проект добавить какую-то из этих библиотек, надо нажать по ней два раза кнопкой мыши (или выделить и нажать "ок"). Для примера добавим System.Net. Видим, что она появилась в общем списке
Но это далеко не все доступные нам библиотеки. Если мы нажмём на кнопку обзор и зайдём в папку с ZennoPoster, то увидим множество dll, которые также можно добавить. Для примера добавим Newtonsoft.json, которая нужна для работы с JSON
Помимо того, что тут есть, мы можем добавлять и сторонние библиотеки. Закидывать и надо в папку ExternalAssemblies, ну а далее точно также жмём "обзор" и добавляем. Что при этом важно учесть:
- У нас в ZennoPoster используется .Net Framework 4.6.2, в то время как весь мир сидит уже на .Net. Поэтому прежде чем добавлять библиотеку, убедитесь, что добавляемая библиотека совместима с .Net Framework 4.6.2 (т.е. ищите старые версии библиотек)
- Сами dll можно искать как где-то на форумах, так и скачивать с Nuget, используя Visual Studio (позже будет видео).
Знакомимся с общим кодом
Добавляем общий кодВ самом верху у нас прописаны директивы using. Это подключенные пространства имён. Можно обойтись и без них, но тогда вам придётся писать полный путь при обращении к классам (имя_пространства_имен.название_класса.название_метода()). Например, чтобы нам вызвать File.Move(...), нам надо будет написать System.IO.File.Move().
Возможно вы также заметили вверху две вкладки: "общий код" (это где мы сейчас находимся) и "директивы using".
Так вот, вкладка "директивы using" нужна именно для кубиков c#. Т.е. если вы добавили какую-то библиотеку и не хотите прописывать полный путь начиная с пространства имен, вам надо будет прописать директиву using именно в этой вкладке.
Вернёмся к общему коду. После директив using мы с вами видим namespace ZennoLab.OwnCode {}. Вспоминаем, что namespace (пространство имён) по сути просто коробка для классов. Далее у нас идёт сам класс public class CommonCode{}, внутри которого мы уже можем создавать свои свойства и методы
Давайте мы с вами переместим наш код клика, написанный в кубике c# в общий код. Для этого внутри класса создаём метод
Наш метод состоит из модификатора доступа (public), возвращаемого значения (void), имени (Click) и параметров (IZennoPosterProjectModel project, Instance instance)
- Модификаторы доступа нужны для того, чтобы понять, где этот метод можно будет использовать. Написав public мы сказали, что этот метод будет доступен везде (в том числе и кубике c#). Бывает также internal (почти тоже самое, что public), protected (в наследуемых классах) и private (только в этом классе, т.е. в кубике c# он уже доступен не будет)
- Методы могут не возвращать значений (пишем void), а могут и вернуть абсолютно любой тип (тогда указываем его. например string, int, bool, HtmlElement и т.д.). Мы это уже проходили.
- Имя может быть почти любым. Действуют те же правила, что и для имён переменных. Публичные (public) методы принято называть с большой буквы, а приватные (private) с маленькой
- Про параметры вы тоже уже знаете. Объясню, зачем мы с вами прописали IZennoPosterProjectModel project, Instance instance. Дело в том, что по умолчанию в общем коде объекты project и instance недоступны. Если мы хотим их использовать, нам надо их "перекинуть" из кубика c# в общий код. Позже ещё коснёмся этой темы. А пока же просто имейте ввиду, что вам надо прописать эти параметры, если хотите в своём методе воспользоваться project или instance
Нам осталось научиться вызывать наш метод из кубика c#. Для этого нам надо создать экземпляр данного класса, а затем обратиться к нашему методу Click(), не забыв передать project и instance в качестве параметров
C#:
CommonCode myname = new CommonCode();
myname.Click(project, instance);
Возвращаемое значение методов
Вспоминаем наши первые уроки. Методы могут как возвращать какое-то значение, так и нет. Если метод ничего не возвращает, мы пишем void. Если же да, то пишем тип, который он возвращает. А в самом коде в самом конце мы должны прописать return возвращаемая_переменная. В предыдущем примере мы с вами написали метод клика, вот только логика ожидания элемента зашита прямо в него. Это не очень хорошо, т.к. ожидание элемента нужно не только при совершении клика, но и при вводе текста, при парсинге и т.д. Давайте вынесем этот код в отдельный метод WaitElement(). Создаем новый метод с этим именем
C#:
public HtmlElement WaitElement(IZennoPosterProjectModel project, Instance instance, string xpath)
{
HtmlElement el = null;
Tab tab = instance.ActiveTab;
Random r = new Random();
for (int i = 0; i<30; i++)
{
//пробуем отыскать элемент
el = tab.FindElementByXPath("//div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]", 0);
//если найден, пауза и выходим из цикла
if (!el.IsVoid)
{
Thread.Sleep(r.Next(1000, 3000));
break;
}
//выход по ошибке, если элемент не появился
if (i == 29) throw new Exception("не дождались появления элемента //div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]");
//пауза 1 сек
project.SendInfoToLog("ждём появления элемента //div[@data-hydration-id]/a[contains(@href, 'ya.ru' )]");
Thread.Sleep(1000);
}
return el;
}
Теперь мы можем удалить лишний код из метода Click и прописать туда метод WaitElement. Я также добавил параметр xpath, чтобы мы могли передавать xpath путь до элемента
C#:
public void Click(IZennoPosterProjectModel project, Instance instance, string xpath)
{
HtmlElement el = null;
Tab tab = instance.ActiveTab;
Random r = new Random();
el = WaitElement(project, instance, xpath);
//клик
tab.FullEmulationMouseMoveToHtmlElement(el);
Thread.Sleep(r.Next(300, 1000));
tab.FullEmulationMouseClick("left", "click");
//ожидание загрузки и пауза
if (tab.IsBusy) tab.WaitDownloading();
Thread.Sleep(r.Next(1000, 3000));
}
Параметры методов
Вы можете передавать сколько угодно параметров какого угодно типа. Мы также можем передавать необязательные параметры, которые будут иметь значение по умолчанию. Единственное, идти они должны только после обязательных параметров. Давайте "прокачаем" наш метод Click, добавив возможность выбирать, будем ли мы эмулировать мышку и будем ли мы брать паузы до и после кликов
C#:
public void Click(IZennoPosterProjectModel project, Instance instance, string xpath, bool emulationMouse, bool sleep=true)
{
HtmlElement el = null;
Tab tab = instance.ActiveTab;
Random r = new Random();
el = WaitElement(project, instance, xpath);
//клик
if(emulationMouse)
{
tab.FullEmulationMouseMoveToHtmlElement(el);
Thread.Sleep(r.Next(300, 1000));
tab.FullEmulationMouseClick("left", "click");
}
else
{
el.Click();
}
//ожидание загрузки и пауза
if(sleep)
{
if (tab.IsBusy) tab.WaitDownloading();
Thread.Sleep(r.Next(1000, 3000));
}
}
Приватные методы
Выше я упомянал про то, что методы с модификатором public доступны везде, а private только в своём классе. Смотрите, сейчас наш метод WaitElement() доступен как в текущем классе, так и в любом другом (в том числе кубике c#). Давайте убедимся в этом
Но по сути зачем нам публичный метод WaitElement? Едва ли мы будем использовать его в кубике c#. Поэтому давайте поменяем public на private и убедимся, что он больше недоступен в кубике c#
К слову, если вы вообще не пропишите модификатор доступа для метода, то он будет считаться private. А если вы не пропишите модификатор доступа для класса, то он будет считаться internal
Возвращаем несколько значений через out
Бывают ситуации, что нам нужно вернуть несколько значений из метода. В таком случае можно использовать вот такую штуку
Общий код
C#:
public void test(out string result1, out string result2)
{
//любая логика
//по ходу кода
result1 = "Возвращаемое значение 1";
//любая логика
//по ходу кода
result2 = "Возвращаемое значение 2";
}
C#:
CommonCode myname = new CommonCode();
string res1=string.Empty, res2=string.Empty;
myname.test(out res1, out res2);
project.SendInfoToLog($"{res1}\n{res2}");
- В методе параметры передать с использованием out
- вернуть эти значения по ходу выполнения кода, просто присвоив им нужное значение
- В кубике c# (или другом методе) создать переменные
- когда будем вызывать метод, мы прописываем их с использованием out
Конструктор
У классов есть такая штука, как конструктор. В нём происходит инициализация объекта, т.е. мы можем с вами прямо при создании экземляра класса присвоить значения каким-то переменным, выполнить проверки и т.д. Конструктор – это как метод, который выполняется сразу при создании экземпляра класса.
В коде выше нам приходилось в каждый метод передавать instance и project, чтобы их использовать. Мы можем с вами воспользоваться конструктором, дабы этого не делать. Имя конструктора должно совпадать с именем класса.
C#:
public class CommonCode
{
/// <summary>
/// Lock this object to mark part of code for single thread execution
/// </summary>
public static object SyncObject = new object();
IZennoPosterProjectModel project;
Instance instance;
Tab tab;
public CommonCode(IZennoPosterProjectModel _project, Instance _instance)
{
project = _project;
instance = _instance;
tab = instance.ActiveTab;
}
/// <summary>
/// Метод перехода на страницу
/// </summary>
/// <param name="url">куда переходим</param>
public void Navigate(string url)
{
tab.Navigate(url);
tab.WaitDownloading();
}
// Insert your code here
}
C#:
CommonCode com = new CommonCode(project, instance);
com.Navigate("zennolab.com");
Поля и свойства
Полями в общем коде называют обычные переменные. Их принято делать только приватными. Это означает, что пользоваться ими мы сможем только в том классе, в котором их создали. Т.е. например, в кубике c# вы их не увидите. В примере выше полями у нас являются
C#:
IZennoPosterProjectModel project;
Instance instance;
Tab tab;
C#:
string name;
int age;
Чтобы они стали доступными, нам нужно добавить модификатор public.
C#:
public string name;
public int age;
Но так делать не рекомендуется.
Свойства же – это своего рода "гибрид" между полями и методами. Они используются именно как переменные, но позволяют нам выполнять какие-либо проверки. Например, возраст никак не может быть меньше нуля и именно благодаря свойствам мы с вами можем это контролировать. Свойства уже можно делать публичными, т.е. они могут быть доступны и в других классах, в том числе и кубике c#.
Свойства "работают в связке" с приватными полями.
Давайте вместо поля age создадим свойство Age (публичные члены класса принято называть с большой буквы, а приватные с маленькой) и сделаем так, чтобы нельзя было поставить его меньше нуля.
C#:
int age;
public int Age
{
get
{
if(age < 0) age = 0; //это наша проверка
return age; //а тут мы возвращаем результат
}
set
{
age = value; //означает присвоить устанавливаемое значение
}
}
Как видите, когда мы присвоили 25, мы и получили 25. Но если мы присваиваем -5, то получаем 0 (а не -5).
Если вам не требуются никакие проверки, то можно использовать автосвойства. В этом случае создавать приватное поле для него не требуется.
public string Job {get;set;}
И теперь можно пользоваться им в кубике c# как обычной переменной.
Заключение
По общему коду я пробежался довольно поверхностно и возможно кого-то запутал. Вам надо просто начать его использовать, и вы начнете потихоньку "въезжать". Без его освоения полноценно писать на C# нет смысла, но юзать какие-то сниппеты можно.
Чтобы не удлинять статью ещё больше, я вам в отдельном файле прикрепил шпаргалку по ZennoPoster API и некоторым распространенным классам .Net. Там есть примеры кода, которые можно вставлять в кубик c# и смотреть, что происходит. Пользуйтесь.
Надеюсь, эта статья была кому-то полезна и теперь c# стал для вас чуточку проще, чем до её прочтения. Всех благ.
Видео - https://youtu.be/CPzjZJxzA44
Вложения
-
404,7 КБ Просмотры: 27
Последнее редактирование: