Ежедневник IT-ка
133 subscribers
22 photos
4 videos
1 file
43 links
Программируем на практике!!
По вопросам по поводу проектов: @vladimir_dzen
Download Telegram
Иногда, быстро необходимо создать класс из Json. Для этих целей есть различные сайты, но мне понравился:
json2csharp.com . Достаточно интуитивный и простой.

#Csharp,#Json
🖥 В этом видео происходит знакомство с классом и ООП.

смотреть видео

#Csharp,#видео
❗️Внимание. Для тех, кто разрабатывает проекты используя WPF.

XAML Behaviors для WPF теперь Open Source.

В прошлом году мы открыли исходный код XAML Behaviors для UWP, который имел большой успех, и пакет Behaviors NuGet был загружен более 500 000 раз. XAML Behaviors для WPF теперь поставляется в виде пакета NuGet — Microsoft.Xaml.Behaviors.Wpf. Подробнее под катом!

Это позволит быстрее добавлять новые фичи и исправлять ошибки. Когда новый Behavior или фича добавляется в репозиторий, их можно будет использовать практически сразу. Открытость для исправлений позволяет платформе Behaviors развиваться, предоставляя сообществу возможность задавать темп и направление. Хотя вы можете продолжать использовать Extension SDK, дальнейшая разработка будет осуществляться только на GitHub и будет опубликована в пакете NuGet в новом пространстве имен Microsoft.Xaml.Behaviors.

ссылка на полную статью.

#Csharp,#WPF,#XAML
👆 Очередной xpath запрос для нахождения нужной информации.

#ZennoPoster,#Xpath
👆 Одна из ситуаций, когда при парсинге Json , получили ❗️исключение❗️. Поэтому, как выход, скрипт пытается найти необходимое значение и заменить его самостоятельно.

#ZennoPoster,#Xpath,#Json
​​Пример использования HttpClient для работы с запросами:

1. Подключаем пространство имён.

using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.IO;

2. Создаём класс.

 public class Poster
 {
  public int Id { get; set; }
  public int MovieId { get; set; }
  public string Name { get; set; }
 }

3. Создаем новый экземпляр класса.

private static HttpClient _httpClient = new HttpClient();

4. Устанавливаем свойства текущ.-их методов.

_httpClient.BaseAddress = new Uri("http://localhost:987456");
_httpClient.Timeout = new TimeSpan(0, 0, 30);
_httpClient.DefaultRequestHeaders.Clear();

5. Создаём асинхронный метод(для того, чтобы не блокировать основной поток).

 private async Task<string> GetResourceThroughHttpRequestMessage()
{

   5.1. Создаем новый экземпляр класса.

   var request = new HttpRequestMessage(
    HttpMethod.Get,
    $"api/books/6e0drwqt/posters/{Guid.NewGuid()}");

   5.2. Добавляем тип контента(Content-Type) в   заголовок.

    request.Headers.Accept.Add(new  MediaTypeWithQualityHeaderValue("application/json"));

   5.3. Делаем асинхронный запрос к серверу.

   using (var response = await _httpClient.SendAsync(request))
   {

    5.4. Проверяем полученный код статуса запроса.

    response.EnsureSuccessStatusCode();

    5.5. Читаем полученный ответ.

    var stream = await response.Content.ReadAsStreamAsync();
    using (var streamReader = new StreamReader(stream))
    {
     using (var jsonTextReader = new JsonTextReader(streamReader))
     {
      var jsonSerializer = new JsonSerializer();

      5.6. Устанавливаем значения из Json в объект класса Poster.

      var poster = jsonSerializer.Deserialize<Poster>(jsonTextReader);

      5.7. Получаем значение одного из свойств объекта класса Poster.

      return poster.Name;
     }
    }
   }
}

#HttpClient, #Csharp
This media is not supported in your browser
VIEW IN TELEGRAM
Для того, чтобы использовать в пространстве имён библиотеку Newtonsoft.Json(как пример), необходимо её установить.
Установка пакета(ов) будем производить, через NuGet (систему управление пакетами).
Задача довольно простая и тривиальная, но многие новички теряются и не знают, что и как делать.

#Csharp,#видео
​​В группе будут публиковаться различные посты, которые будут связаны с программным комплексом ZennoPoster.
Он используется мною очень часто т.к. помогает решить, большое кол-во задач связанных с автоматизацией, которые ведутся через браузер.
Самое главное его преимущество, что у него очень большое сообщество и его постоянно совершенствуют.

#ZennoPoster
Указано то, на что стоит всегда обращать внимание.
С другими ответами при выполнение Http запросов, можно ознакомится здесь.

#HTTP
​​Необходимо помнить, что повторные Http запросы надо блокировать т.к. это может привести к ошибкам, а именно "могут исчерпаться все доступные TCP соединения"

1. Подключаем пространство имён.

using System.Net.Http;
using System.Threading.Tasks;

static async Task Main(string[] args)
{
  await ReuseQuery();
}

2. Создаём асинхронный метод(что это такое, очень хорошо написано, здесь).

    public static async Task<string> ReuseQuery()
    {
      string result = string.Empty;

2.1. Создаём экземпляра класса.

      using (var client = new HttpClient())
      {

2.2. Обязательно цикл делать внутри конструкции using(для
того, чтобы повторные запросы происходили, через 1 TCP
соединение)

        for (int i = 0; i < 5; i++)
        {
          var request = new HttpRequestMessage(HttpMethod.Get,
            "google.com");

2.3. Делаем запрос.

          using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
          {

2.4. Читаем полученные данные.

            result = await response.Content.ReadAsStringAsync();
            response.EnsureSuccessStatusCode();
          }
        }
      }
      return result;
    }
  }

#Csharp,#HTTP
​​Продолжаю работать с ZennoPoster - ом, который помогает решить различные задачи.
Рассмотрим часть примера, одного из моих заказов.
Необходимо получать рандомную информацию о человеке(его адрес), в качестве донора используется
этот сайт.
​​После того, как нашли необходимый тег, получаем более детальную информацию в свойствах элемента.
В своей практике использую очень часто Xpath и Linq запросы, которые помогают более точно найти и обработать необходимые элементы.

#ZennoPoster
​​Часто бывают случаи необходимо работать с Json, который представляет собой элемент с вложенной структурой.

Пример:

{
 "clientKey": "fdfggghhttyydshkahue26",
 "task": {
  "cookies": "",
  "type": "NoCaptchaTaskProxyless",
  "websiteURL": "https://www.somesite/ru/login",
  "websiteKey": "6LcMERGSGSGSHHHS-KcbYQMd-wcLt6ight7u"
  }
}

Рекомендую разбивать подготовительный этап на определённые шаги.

1. Подключение пространство имён.

using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.IO;
using System.Text;

2. Создание объектов классов.

  public class CreateTaskRecaptcha
  {
    public string clientKey { get; set; }
    public DataForCreateTaskRecaptcha task { get; set; }
  }
  public class DataForCreateTaskRecaptcha
  {
    public string cookies { get; set; }
    public string type { get; set; }
    public string websiteURL { get; set; }
    public string websiteKey { get; set; }
  }
  public class ResultRecaptcha
  {
    public int errorId { get; set; }
    public string status { get; set; }
    public int taskId { get; set; }
    public string errorDescription { get; set; }
  }

3. Создаём метод, который возвращает экземпляр объект класса с необходимыми заголовками.

    public static HttpClient CreateHttpClient()
    {
      var client = new HttpClient();
      client.Timeout = new TimeSpan(0, 0, 30);
      client.DefaultRequestHeaders.Clear();
      client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36");
      client.DefaultRequestHeaders.Add("Accept", "*/*");
      client.DefaultRequestHeaders.Add("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
      client.DefaultRequestHeaders.Add("Connection", "keep-alive");
      return client;
    }

4. Создаём обязательно асинхронный метод, который возвращает метод класса.

    private async Task<int> GetPostThroughHttpRequest(HttpClient client)
    {

4.1. Переменные которые хотим передать.

      string websiteURL = "https://www.google.com/";
      string websiteKey = "6LcMERGSGSGSHHHS-KcbYQMd-wcLt6ight7u";
      string clientKey = "fdfggghhttyydshkahue26";
      string uri = "https://somesite.com/auth/login";

4.2. Передадим значения переменных в наш объект класса.

      var dict = new CreateTaskRecaptcha
      {
        task = new DataForCreateTaskRecaptcha
        {
          cookies = "",
          type = "NoCaptchaTaskProxyless",
          websiteURL = websiteURL,
          websiteKey = websiteKey
        },
        clientKey = clientKey
      };

4.3. Создадим Json из объекта класса.

      string bodyJson = JsonConvert.SerializeObject(dict);

4.4. Установим формат нашего тело запроса.

      var body = new StringContent(bodyJson, Encoding.UTF8, "application/json");

4.5. Делаем запрос.

      var response = await client.PostAsync(uri, body);

4.6. Читаем полученный ответ от сервера.

      string content = await response.Content.ReadAsStringAsync();

4.7. Конвертируем полученный ответ в Json и передаём его в наш объект класса.

      var jsonResult = JsonConvert.DeserializeObject<ResultRecaptcha>(content);
      if (jsonResult.errorId > 0) Console.WriteLine(jsonResult.errorDescription);

4.8. Получаем необходимый метод с нашего объекта класса.

      return jsonResult.taskId;
    }

Пример показывает работу с вложенной структурой Json и Http запросами, которые нам надо передать.

#Csharp,#HTTP
​​Хочу поделиться с одной из программ, которую использую для тестирования GET и POST запросов.
Более подробнее с ней можно ознакомится на postman.
Для меня она интересна тем, что в ней предоставляется только необходимые инструменты, для анализа данных + всё можно конвертировать в любой из предоставленных языков программирования.

#Postman
​​Рефлексия - это процесс, который позволяет программе изучать саму себя.
Звучит довольно интересно и интригующе, в практике позволяет:
- перечислять члены типа
- извлекать информацию о типе
- извлекать информацию о сборке
- исследовать пользовательские атрибуты
Надо понимать, что это всё применимо для общедоступных (public) методов из заданного типа.

Рассмотрим простой пример(реализован в WPF приложение):

1. Создаём объект класса(это отдельный файл с расширением .cs).

namespace HumanizerDemo
{
  public class Binance
  {
    public int BalanceUSD { get; set; }
    public int BalanceBTC { get; set; }
    public Binance(int n, int a)
    {
      BalanceUSD = n;
      BalanceBTC = a;
    }

    public int CalculateCount(int countUsd, int priceBtc)
    {
      return countUsd / priceBtc;
    }
  }
}

2. При создание проекта WPF автоматически создаётся файл MainWindow.xaml с разметкой(это, то что у меня):

<Window x:Class="HumanizerDemo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:HumanizerDemo"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
  <Grid>

  </Grid>
</Window>

2.1. В этот код добавляем:

- элемент компоновки "StackPanel",
- текстовый элемент "TextBlock",
- элемент кнопки "Button"

  <Grid>
    <StackPanel>
      <Button Name="GetHumanMethodNames" Click="GetHumanMethodNames_OnClick">Получение методов</Button>
      <TextBlock Name="Output"></TextBlock>
    </StackPanel>
  </Grid>

Продолжение следует...

#Рефлексия, #Csharp, #WPF
​​Продолжаем знакомство с программным комплексом ZennoPoster.

В примере показано:
- работа в многопоточном режиме
- чтение *.txt файлов
- сохранение содержимого *.txt файла в таблицу
- чтение и запись данных в таблицу
- конвертирование таблицы в список
- сохранение списка в *.txt файл

1. Получаем таблицу по имени созданную в проекте ZennoProject используя интерфейс IZennoTable

var sourceTable = project.Tables["Accounts"];

2. Инициализируем новый список класса List<T>

var sourceListFromTask = new List<string>();

3. Сохраняем в переменную "путь нашего файла", с которым работаем

string pathFile = Path.Combine(project.Directory, "account.txt");

4. FileLocker - это созданный нами объект синхронизации в общем коде ZennoProject, расположенный в классе CommonCode.

public static object FileLocker = new object();

4.1. Обязательно лочим наш поток(для того, чтобы другие
потоки не имели доступа к файлу),

lock (CommonCode.FileLocker)
{
4.2. Проверяем существование нашего файла, чистим таблицу
и инициализируем переменные.

if (File.Exists(pathFile))
{
sourceTable.Clear();
String line;
bool insertLine = true;

4.3. Читаем файл используя класс StreamReader,который
позволяет работать с файлом как хранилищем символов, и
такой подход более эффективен.

using (StreamReader sr = new StreamReader(@pathFile, Encoding.UTF8))
while ((line = sr.ReadLine()) != null)

4.4. Добавляем наши строки из файла в таблицу.

sourceTable.AddRow(line);

4.5. В цикле проверяем строки из таблицы и если выполняются необходимые условия, то сохраняем значения в переменные проекта.

for (int indexOfRow = 0; indexOfRow < sourceTable.RowCount; indexOfRow++)
{
string value = sourceTable.GetCell("C", indexOfRow).Trim();
if (string.IsNullOrEmpty(value) && insertLine)
{
project.Variables["emailAcc"].Value = sourceTable.GetCell("A", indexOfRow).Trim();
project.Variables["passAcc"].Value = sourceTable.GetCell("B", indexOfRow).Trim();
sourceTable.SetCell("C", indexOfRow, "Checking");
insertLine = false;
}
}

4.6. Переносим строки из таблицы в список, для того, чтобы
сохранить их в файл(использую  Linq запрос).

int column = 0;
Enumerable.Range(0, sourceTable.RowCount).ToList().ForEach(i => sourceListFromTask.Add(String.Join(":", sourceTable.GetRow(i))));

4.7. Сохраняем строки списка в файл используя класс
StreamWriter

using (StreamWriter sw = new StreamWriter(pathFile, false, Encoding.UTF8))
{
sw.WriteLine(string.Join("\r\n", sourceListFromTask));
}
}
}

Скриншот кода в проекте.

#ZennoPoster, #Сниппеты
​​Продолжаем знакомство с рефлексией, и будем получать информацию о классе и о методах в нём.

Рассматриваем проект, который реализовали ранее.

1. Открываем файл "MainWindow.xaml.cs", который был создан автоматически.

2.Подключаем пространство имён.

using System;
using System.Reflection;
using System.Windows;

3. Метод который описывает действие, которое происходит при нажатие на кнопку(которую создали в прошлый раз).

    private void GetHumanMethodNames_OnClick(object sender, RoutedEventArgs e)
    {

3.1. Имя нашего текстового блока, который расположен в
нашей разметке.

      Output.Text = "";

3.2. Поучаем экземпляр класса Туре, в котором прописываем
"полное имя типа(нашего класса) в строковом
представлении".

var infoAboutClass = Type.GetType("HumanizerDemo.Binance",false,true);

3.3. Устанавливаем размер шрифта, для нашего текстового
блока.

      Output.FontSize = 16;

3.4. Получаем разную информацию о классе с помощью
методов класса Type.

      Output.Text += "Получаем разную информацию о классе с помощью методов класса Type";
      Output.Text += Environment.NewLine;
      Output.Text += Environment.NewLine;
      Output.Text += "Полное Имя: " + infoAboutClass.FullName;
      Output.Text += Environment.NewLine;
      Output.Text += "Базовый класс: " + infoAboutClass.BaseType.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "Абстрактный: " + infoAboutClass.IsAbstract.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "Запрещено наследование: " + infoAboutClass.IsSealed.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "class: " + infoAboutClass.IsClass.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += "Публичный: " + infoAboutClass.IsPublic.ToString();
      Output.Text += Environment.NewLine;
      Output.Text += Environment.NewLine;

3.5. Получаем информацию о методах, которые существуют в
этом классе.

      MethodInfo[] mi = infoAboutClass.GetMethods(BindingFlags.Instance
          | BindingFlags.Static
          | BindingFlags.Public
          | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);

      Output.Text += "Получаем информацию о методах";
      Output.Text += Environment.NewLine;
      Output.Text += Environment.NewLine;
      foreach (MethodInfo imi in mi)
      {
        Output.Text += "Полное Имя: " + imi.Name.ToString();
        Output.Text += Environment.NewLine;
      }
    }

Рассмотрел простейшие примеры, но уже и они показывают возможности рефлексии, которые помогают нам узнать некоторые вещи.

#Рефлексия, #Csharp
​​Работа со временем и датами - это одна из тех задач, которую необходимо делать в программирование очень часто. Ведь актуальность данных это, то на чём держится современный мир(ушёл от темы).
Мы также не будем отставать и будем работать со временем.

Задача: рассчитать среднее кол-во времени размещение постов в группе(наш случай) согласно сервиса telemetr.me .

Работаем в программном комплексе ZennoPoster, который отлично справляется с анализом структурой страницы.

1. Для того, чтобы получить все "времена длительности"(назовём это так), то мы должны понять в каком из тегов они находятся т.е. подготовить предварительные данные.
Из структуры страница сайта, мы понимаем, что вся нужная информация находится в одном главном для нас теге "tr". Находим его.

1.1. Обращаемся к свойству('ActiveTab') объекта('instance') и передаём полученную информацию в класс('Tab').

Tab tab = instance.ActiveTab;

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

1.2. Получаем Все необходимые элементы, которые находятся в текущей вкладке нашего браузера, с помощью XPath запроса и передаём в класс('HtmlElementCollection' - который работает с группой элементов).

HtmlElementCollection entries = tab.FindElementsByXPath("//tr");

1.3. Если кол-во найденных элементов ('tr'), больше 0, то идём дальше.

1.4. Инициализируем переменные.

var lstTemp = new List<string>();
var totalTimePublicPostAdvertise = string.Empty;
var content = string.Empty;

if (entries.Count > 0)
{

1.5. Проходим в цикле по всем свойствам('InnerHtml'), полученных тегов tr, в которых и расположена нужная информация.

for (int x = 0; x < entries.Count; x++)
{
content = entries.Elements[x].InnerHtml;

1.6. ОБЯЗАТЕЛЬНО весь наш последующий
код должен быть расположен в
конструкции(try..catch), для того, чтобы при
возникновение ошибок, код понимал,
что делать в этом случае.

try{

1.7. Получаем информацию с необходимого тега('span' с названием класса 'kt-font-brand'), с помощью XPath запроса, используя метод ParseByXpath и сохраняем полученные данные в список.

lstTemp =
ZennoPoster.Parser.ParseByXpath(content,
"//span[contains(@class,'kt-font-brand')]",
"innerText").ToList();

totalTimePublicPostAdvertise =
lstTemp[0].Trim().Replace("'", @"''");

}catch (Exception ex){

1.8. Отправляем ошибку в лог ZennoPoster.

project.SendErrorToLog(ex.Message, true);
}
}

Продолжение следует...

#ZennoPoster, #Дата