• Как работать с ценами в разной валюте?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Хранить значения в одной (универсальной) валюте. С сортировкой проблем быть не должно. Что касается фильтрации, то просто конвертировать значение фильтра в универсальную валюту.

    Например, цены хранятся в долларах США. Клиент хочет посмотреть цены от 100 рублей, тогда 100 рублей нужно конвертировать в доллары США и подставить это значение в запрос на выборку.

    При выводе можно конвертировать на лету, выводиться ведь будет немного записей. В крайнем случае, если будут проблемы с производительностью, можно кешировать.
    Ответ написан
    Комментировать
  • Сохранения и чтения cookie, из текстового файла в xNet?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Использовать базу данных :-)

    Можно попробовать сериализовать CookieDictionary, но Dictionary видимо намекает, что это будет непросто. Если не получится, то можно попробовать сделать свой, сериализуемый, CookieDictionary и использовать его.

    С JSON наверное проблем будет меньше, по крайней мере обычный Dictionary с помощью Newtonsoft.Json можно без проблем сериализовать/десериализовать.

    Можно попробовать с CookieDictionary, примерно так:

    // получаем json:
    string json = JsonConvert.SerializeObject(cookieDictionary);
    
    // получаем экземпляр CookieDictionary из json:
    var cookieDictionary2 = JsonConvert.DeserializeObject<CookieDictionary>(json);

    Если с сериализацией будут проблемы и при преобразовании экземпляра CookieDictionary в строку на выходе всегда получается строка вида: ключ=значение; ключ=значение, то можно разбить эту строку и получить коллекцию:

    // string cookiesRaw = File.ReadAllText(string.Format("Cookies_{0}.txt", textBox1.Text));
    string cookiesRaw = "ключ1=значение1; ключ2=значение2";
    var cookies = cookiesRaw.Split(';').Select(itm => itm.Split('=')).
                  ToDictionary(k => k[0].Trim(), v => v[1].Trim());

    В переменной cookies будет экземпляр Dictionary, который можно попробовать преобразовать в CookieDictionary (зависит от реализации), либо создать и наполнить экземпляр CookieDictionary.

    httpRequest.Cookies = new CookieDictionary();
    
    foreach(var item in cookies)
    {
      httpRequest.Cookies.Add(item.Key, item.Value);
    }
    Ответ написан
    2 комментария
  • Как в цикле считать XML?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    1. Использовать XML-сериализацию (все данные будут загружены в память).

    Классы
    public class Backup
    {
    
      public Basic Basic { get; set; }
    
      public List<Base> Bases { get; set; }
    
    }
    
    public class Basic
    {
    
      public string Path1C { get; set; }
    
    }
    
    public class Base
    {
    
      [XmlAttribute]
      public string Name { get; set; }
    
      [XmlAttribute]
      public string Mode { get; set; }
    
      [XmlAttribute]
      public string Path { get; set; }
    
    }
    Пример использования
    // из строки
    string source =
    (
      @"<?xml version=""1.0"" encoding=""utf-8"" ?>
      <Backup>
        <Basic>
          <Path1C>\\server\1cv8s.exe</Path1C>
        </Basic>
        <Bases>
          <Base Name=""b1"" MODE=""File"" Path=""\\server\Base\base""/>
          <Base Name=""bas2"" MODE=""Server"" Path=""\\server\db""/>
        </Bases>
      </Backup>"
    );
    
    
    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(source)))
    {
      var serializer = new XmlSerializer(typeof(Backup));
      var backup = (Backup)serializer.Deserialize(ms);
    
      foreach (var b in backup.Bases)
      {
        Console.WriteLine("Name: {0}", b.Name);
        Console.WriteLine("MODE: {0}", b.Mode);
        Console.WriteLine("Path: {0}", b.Path);
      }
    }

    2. Для чтения небольших файлов можно использовать System.Xml.XmlDocument (все данные будут загружены в память):

    var xml = new XmlDocument();
    
    // из файла:
    // xml.Load("XMLFile1.xml");
    
    // из строки
    xml.LoadXml
    (
      @"<?xml version=""1.0"" encoding=""utf-8"" ?>
      <Backup>
        <Basic>
          <Path1C>\\server\1cv8s.exe</Path1C>
        </Basic>
        <Bases>
          <Base Name=""b1"" MODE=""File"" Path=""\\server\Base\base""/>
          <Base Name=""bas2"" MODE=""Server"" Path=""\\server\db""/>
        </Bases>
      </Backup>"
    );
    
    // читаем и выводим все элементы Base из /Backup/Bases:
    foreach (XmlNode n in xml.SelectNodes("/Backup/Bases/Base"))
    {
      Console.WriteLine("Name: {0}", n.Attributes["Name"].Value);
      Console.WriteLine("MODE: {0}", n.Attributes["MODE"].Value);
      Console.WriteLine("Path: {0}", n.Attributes["Path"].Value);
    }

    3. Для больших файлов лучше использовать System.Xml.XmlReader (нагрузка на память минимальная). Для простоты работы, сделать комбинацию из выше указанных методов.

    Очень простой, но грубый пример использования XmlReader
    string source =
    (
      @"<?xml version=""1.0"" encoding=""utf-8"" ?>
      <Backup>
        <Basic>
          <Path1C>\\server\1cv8s.exe</Path1C>
        </Basic>
        <Bases>
          <Base Name=""b1"" MODE=""File"" Path=""\\server\Base\base""/>
          <Base Name=""bas2"" MODE=""Server"" Path=""\\server\db""/>
        </Bases>
      </Backup>"
    );
    
    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(source)))
    // если из файла, то без MemoryStream; или лучше использовать FileStream
    // using (var xml = XmlReader.Create("XMLFile1.xml"))
    using (var xml = XmlReader.Create(ms))
    {
      while (xml.Read())
      {
        switch (xml.NodeType)
        {
          case XmlNodeType.Element:
            // нашли элемент Base
            if (xml.Name == "Base")
            {
              // выводим атрибуты
              Console.WriteLine("Name: {0}", xml.GetAttribute("Name"));
              Console.WriteLine("MODE: {0}", xml.GetAttribute("MODE"));
              Console.WriteLine("Path: {0}", xml.GetAttribute("Path"));
            }
            break;
        }
      }
    }
    Ответ написан
    Комментировать
  • ASP.NET не видит статичные файлы в папке Views/Home?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Файл ведь физически находятся в папке /Views/Home/bg.jpg, но скорее всего это не будет работать. Папка /Views предназначения только для файлов представлений, частичных представлений и шаблонов. Обычная (ожидаемая) обработка файлов в этой папке должна быть по умолчанию запрещена.

    Для статичных файлов предназначена папка /Content.

    Для файлов скриптов можно использовать папку /Scripts.
    Ответ написан
    4 комментария
  • Как сделать путь к файлу через textbox?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Видимо нужно указать имя файла в первом параметре:
    var file1 = new Attachment(textBox9.Text + "1.png");

    Вторым параметром может быть указан тип содержимого, в данном случае image/png:

    var file1 = new Attachment(textBox9.Text + "1.png", "image/png");


    PS: Для объединения путей лучше использовать функцию System.IO.Path.Combine(), это избавит от проблем со слешами:
    var file1 = new Attachment(Path.Combine(textBox9.Text, "1.png"), "image/png");
    Ответ написан
    Комментировать
  • Как enum'у назначить regex "любое число"(См.описание)?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    В перечислениях допустимы только целочисленные значения (byte, sbyte, short, ushort, int, uint, long и ulong), либо char.

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

    Вместо перечислений можно использовать константы (const) или readonly переменные. В последнем случае возможности по использованию различных типов данных не ограничены, в отличие от констант. Код для проверки все равно придется написать.
    Ответ написан
    Комментировать
  • Как можно преобразовать MatchCollection в массив строк в c#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Либо циклом пройтись и собрать массив/коллекцию:
    var result = new List<string>();
    
    foreach (Match m in matches)
    {
      result.Add(m.Value);
    }
    
    // в result будет коллекция строк

    Либо можно использовать System.Linq:

    using System.Linq;
    var stringArray = matches.Cast<Match>().Select(m => m.Value).ToArray();

    Как-то показывал пример решателя, но на VB.NET. При желании, можно на C# сделать аналогично.
    Ответ написан
    3 комментария
  • Как сделать связь между объектами в propertygrid?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    В полной мере не понятна суть вопроса. Необходимо чтобы, например, изменяя значение свойства A первого класса, эти изменения отражались в свойстве X второго класса?

    Если так, то вероятно нужно смотреть в сторону события PropertyValueChanged:
    private void propertyGrid1_PropertyValueChanged(Object sender, PropertyValueChangedEventArgs e) 
    {
      System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder();
    
      messageBoxCS.AppendFormat("{0} = {1}", "ChangedItem", e.ChangedItem );
      messageBoxCS.AppendLine();
    
      messageBoxCS.AppendFormat("{0} = {1}", "OldValue", e.OldValue );
      messageBoxCS.AppendLine();
    
      MessageBox.Show(messageBoxCS.ToString(), "PropertyValueChanged Event" );
    }
    Ответ написан
    1 комментарий
  • Какой язык подойдет для запуска и закрытия exe приложений?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Любой язык на это способен :-)

    В C# работа с процессами может быть примерно такой:
    // запускаем процесс
    var process = System.Diagnostics.Process.Start(@"C:\windows\system32\calc.exe");
    // убиваем процесс
    process.Kill();
    // или отправляем команду на закрытие главного окна
    // process.CloseMainWindow();
    
    // запуск можно выполнить через ProcessStartInfo,
    // это может быть более удобней и больше возможностей
    var processStartInfo = new System.Diagnostics.ProcessStartInfo();
    // путь к файлу программы
    processStartInfo.FileName = @"C:\windows\system32\notepad.exe";
    // передаем аргументы (в данном случае путь файла для открытия)
    processStartInfo.Arguments = @"C:\Windows\System32\drivers\etc\hosts";
    
    // запускаем процесс
    var process2 = System.Diagnostics.Process.Start(processStartInfo);
    
    // если необходимо, можем получить список всех процессов
    var processes = System.Diagnostics.Process.GetProcesses();
    
    // для примера, выводим в консоль
    foreach(var p in processes)
    {
      Console.WriteLine("PID#{0}, {1}", p.Id, p.ProcessName);
      // можем поубивать все блокноты
      // if (p.ProcessName == "notepad")
      // {
      //   p.Kill();
      // }
    }

    При запуске процессов, вы можете просто запомнить их идентификаторы (например в коллекцию, типа List<int> или же использовать свой тип, и/или запоминать экземпляры Process) и в последующем завершить работу этих процессов.

    Информацию о запущенных процессах можно получать с помощью методов: System.Diagnostics.Process.GetProcessById() - по идентификатору процесса, System.Diagnostics.Process.GetProcessByName() - по имени процесса.

    Если необходимо, к каждому создаваемому процессу можно подключить обработчик завершения работы процесса:
    // создаем параметры запуска процесса
    var processStartInfo = new System.Diagnostics.ProcessStartInfo();
    processStartInfo.FileName = @"C:\windows\system32\notepad.exe";
    processStartInfo.Arguments = @"C:\Windows\System32\drivers\etc\hosts";
          
    // создаем экземпляр процесса
    var process = new System.Diagnostics.Process();
    // передаем параметры
    process.StartInfo = processStartInfo;
    // разрешаем использование обработчиков событий
    process.EnableRaisingEvents = true; // <-- требуется для работы обработчика завершения процесса
    
    // цепляем обработчик завершения работы процесса 
    // (лучше сделать нормальную функцию, а не анонимную, как показано в примере)
    process.Exited += (object sender, EventArgs e) =>
    {
      // этот блок будет выполнен, когда работа процесса будет завершена
      // экземпляр процесса можно найти в sender: строгий тип - ((System.Diagnostics.Process)sender)
      // (хотя в данном примере без проблем можно использовать process, это будет даже удобней)
    
      // для примера, выводим в консоль идентификатор завершенного процесса
      Console.WriteLine("PID#{0} завершил работу", ((System.Diagnostics.Process)sender).Id);
    };
    
    // запускаем процесс
    process.Start();
    Ответ написан
    3 комментария
  • Как выбрать из json ответа нужные значение?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    С помощью Newtonsoft.Json выполнить поиск по ключам можно так:

    var data = (JObject)JsonConvert.DeserializeObject("данные JSON");
          
    foreach(JObject item in data["response"]["items"])
    {
      // var photos = item.Properties().Where(p => p.Name.StartsWith("photo_")).ToArray();
      // если считать, что последнее изображение самое большое
      var photo = item.Properties().LastOrDefault(p => p.Name.StartsWith("photo_") && 
        p.Value != null && 
        p.Value.ToString() != ""
      );
    
      /*
      // вариант с извлечением номера и сортировкой
      // при условии, что после photo_ всегда будет число
      // (если нет, то придется это учитывать отдельно)
      var photo = item.Properties().Where(p => p.Name.StartsWith("photo_") && 
        p.Value != null && 
        p.Value.ToString() != ""
      ).OrderBy(p => Convert.ToInt32(p.Name.Substring(p.Name.LastIndexOf("_") + 1))).LastOrDefault();
      */
    
      if (photo != null)
      {
        // выводим адрес изображения в консоль
        Console.WriteLine(photo.Value.ToString());
      }
    }
    Ответ написан
    Комментировать
  • Как изменять картинки нажатием на кнопки "вперёд" "назад"?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Это WebFroms или MVC?

    Если WebFroms, то просто сделать обработчик нажатия по ссылке/кнопке, в котором установуть нужный файл в <asp:Image />.

    Например, код на странице может быть таким:
    <asp:LinkButton ID="lnkPrev" 
      Text="Назад" 
      RunAt="server"
      OnClick="lnkPrev_Click"
    />
    
    <asp:Image ID="Image1" 
      ImageUrl="~/img/1.jpg"
      RunAt="server"
    />
    
    <asp:LinkButton ID="lnkNext" 
      Text="Вперёд" 
      RunAt="server"
      OnClick="lnkNext_Click"
    />

    Код обработчиков может быть таким:

    protected void lnkPrev_Click(object sender, EventArgs e)
    {
      // получаем список файлов в папке ~/img
      var files = System.IO.Directory.GetFiles(Server.MapPath("~/img"));
      // текущий путь берем из Image1.ImageUrl
      var currentPath = Server.MapPath(Image1.ImageUrl);
    
      // ищем текущий путь среди полученных файлов
      int index = Array.IndexOf(files, currentPath);
    
      // проверяем, нашлось что-то или нет
      if (index != -1)
      {
        // проверяем, можно получить предыдущий файл или нет
        if (index - 1 > 0)
        {
          // можно, берем его
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index - 1]));
        }
        else
        {
          // нельзя, берем последний из списка
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[files.Length - 1]));
        }
      }
    }
    
    protected void lnkNext_Click(object sender, EventArgs e)
    {
      var files = System.IO.Directory.GetFiles(Server.MapPath("~/img"));
      var currentPath = Server.MapPath(Image1.ImageUrl);
          
      int index = Array.IndexOf(files, currentPath);
    
      if (index != -1)
      {
        // проверяем, есть файлы впереди или нет
        if (files.Length > index + 1)
        {
          // есть, берем следующий файл
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index + 1]));
        }
        else
        {
          // нет, берем первый из списка
          Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[0]));
        }
      }
    }


    При желании, можно сделать один обработчик для обоих ссылок/кнопок с помощью CommandArgument.
    <asp:LinkButton ID="lnkPrev" 
      Text="Назад" 
      RunAt="server"
      CommandArgument="-1"
      OnClick="LinkButton_Click"
    />
    
    <asp:Image ID="Image1" 
      ImageUrl="~/img/1.jpg"
      RunAt="server"
    />
    
    <asp:LinkButton ID="lnkNext" 
      Text="Вперёд" 
      RunAt="server"
      CommandArgument="1"
      OnClick="LinkButton_Click"
    />

    protected void LinkButton_Click(object sender, EventArgs e)
    {
      var lnk = (LinkButton)sender;
      var files = System.IO.Directory.GetFiles(Server.MapPath("~/img"));
      var currentPath = Server.MapPath(Image1.ImageUrl);
          
      int index = Array.IndexOf(files, currentPath);
    
      // если подумать, то этот блок кода можно уменьшить
      if (index != -1)
      {
        if (lnk.CommandArgument == "1")
        {
          if (files.Length > index + 1)
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index + 1]));
          }
          else
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[0]));
          }
        }
        else
        {
          if (index - 1 > 0)
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[index - 1]));
          }
          else
          {
            Image1.ImageUrl = String.Format("~/img/{0}", System.IO.Path.GetFileName(files[files.Length - 1]));
          }
        }
      }
    }


    Для MVC будет совсем по-другому.

    Красивее всего это делать со стороны клиента, с помощью JavaScript.
    Ответ написан
  • Как увеличить количество запросов к серверу за минимальное время?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Попробуйте использовать HttpClient:

    private async Task<string> Get(string url)
    {
      using (var client = new HttpClient())
      {
        using (var r = await client.GetAsync(new Uri(url)))
        {
          return await r.Content.ReadAsStringAsync();
        }
      }
    }

    Но придется вызов метода Get делать с await, и далее по цепочке вверх, добавлять async/await:

    string result = await Get("https://toster.ru/q/470456");

    В качестве альтернативного варианта, можно запускать запросы асинхронно и передавать результат выполнения запроса в функцию. С вашим кодом, примерно так:

    private void Get(string url)
    {
      Task.Run(async () =>
      {
        WebRequest req = WebRequest.Create(url);
        WebResponse resp = await req.GetResponseAsync();
        Stream stream = resp.GetResponseStream();
        StreamReader sr = new StreamReader(stream);
    
        string result = await sr.ReadToEndAsync();
    
        sr.Close();
    
        // передаем результат
        ResultCallback(url, result);
      });
    }
    
    private void ResultCallback(string url, string result)
    {
      // выводим в консоль результат
      Console.WriteLine(url);
      Console.WriteLine(result);
    }

    Аналогичный вариант с HttpClient
    private void Get(string url)
    {
      Task.Run(async () =>
      {
        using (var client = new HttpClient())
        {
          using (var r = await client.GetAsync(new Uri(url)))
          {
            string result = await r.Content.ReadAsStringAsync();
    
            ResultCallback(url, result);
          }
        }
      });
    }
    Обертка кода, указанного в тексте вопроса, с минимальными изменениями
    private void Get(string url)
    {
      // выполняем запрос в отдельном потоке
      Task.Run(() =>
      {
        WebRequest req = WebRequest.Create(url);
        WebResponse resp = req.GetResponse();
        Stream stream = resp.GetResponseStream();
        StreamReader sr = new StreamReader(stream);
    
        string result = sr.ReadToEnd();
    
        sr.Close();
    
        // передаем результат в функцию обратного вызова
        ResultCallback(url, result);
      });
    }
    
    private void ResultCallback(string url, string result)
    {
      Console.WriteLine(url);
      Console.WriteLine(result);
    }
    Вариант с оберткой Thread, если используются старая версия .NET
    private void Get(string url)
    {
      // создаем поток
      var t = new Thread(() =>
      {
        WebRequest req = WebRequest.Create(url);
        WebResponse resp = req.GetResponse();
        Stream stream = resp.GetResponseStream();
        StreamReader sr = new StreamReader(stream);
    
        string result = sr.ReadToEnd();
    
        sr.Close();
    
        ResultCallback(url, result);
      });
    
      // запускаем
      t.Start();
    }
    
    private void ResultCallback(string url, string result)
    {
      Console.WriteLine(url);
      Console.WriteLine(result);
    }
    Ответ написан
    Комментировать
  • Как в WebGrid asp.net mvc поменять количество выводимых страниц?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    @{ 
      var grid = new WebGrid(/*...*/);
    }
    
    @grid.GetHtml(mode: WebGridPagerModes.Numeric, numericLinksCount: 10)
    
    или отдельно список страниц:
    
    @grid.Pager(numericLinksCount: 10)

    https://msdn.microsoft.com/ru-ru/library/system.we...
    public IHtmlString GetHtml(
    	string tableStyle,
    	string headerStyle,
    	string footerStyle,
    	string rowStyle,
    	string alternatingRowStyle,
    	string selectedRowStyle,
    	string caption,
    	bool displayHeader,
    	bool fillEmptyRows,
    	string emptyRowCellValue,
    	IEnumerable<WebGridColumn> columns,
    	IEnumerable<string> exclusions,
    	WebGridPagerModes mode,
    	string firstText,
    	string previousText,
    	string nextText,
    	string lastText,
    	int numericLinksCount,
    	Object htmlAttributes
    )

    numericLinksCount
    Тип: System.Int32
    Число цифровых ссылок на ближайшие страницы WebGrid. Текст каждой цифровой ссылки на страницу содержит номер страницы. Задайте флаг Numeric параметра mode, чтобы эти элементы управления отображались на странице.

    https://msdn.microsoft.com/ru-ru/library/system.we...
    public HelperResult Pager(
    	WebGridPagerModes mode,
    	string firstText,
    	string previousText,
    	string nextText,
    	string lastText,
    	int numericLinksCount
    )

    numericLinksCount
    Тип: System.Int32
    Число отображаемых цифровых ссылок на страницы. По умолчанию используется значение 5.
    Ответ написан
  • Как объеденить массив int в 1 строку C#?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    // входящие данные
    var arr = new int[] { 5, 10, 7, 123, 0 };
    
    // Console.WriteLine(String.Join("+", arr.OrderBy(n => n).Select(n => n.ToString())));
    
    // сортируем
    var sorted = arr.OrderBy(n => n);
    
    // склеиваем
    Console.WriteLine(String.Join("+", sorted.Select(n => n.ToString())));
    
    // или без вызова ToString(), если используемая версия .NET позволит:
    // Console.WriteLine(String.Join("+", sorted));
    
    // или с вызовом ToArray() для ранних версий .NET:
    // String.Join("+", sorted.Select(n => n.ToString()).ToArray())
    Ответ написан
    4 комментария
  • Что означает эта строка в учебнике по NODE?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Если вы сидите под Windows, то меню Пуск => Выполнить => cmd.

    Для перехода к нужному каталогу использовать команду cd. Например, переход в каталог C:\test:

    cd C:\test

    Если каталог находится на другом диске, то потребуется переключиться на этот диск. Например, F:\test:

    rem переключаемся на диск F:
    F:
    rem переходим к каталогу F:\test
    cd F:\test
    Ответ написан
  • Дружба C# и Linux, как?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Можно запускать обычные сборки через Mono или .NET Core. Последнее предпочтительней.

    Программа уровня «Hello world» будет просто запускаться через выше указанные решения, например:

    mono helloworld.exe
    dotnet helloworld.exe
    # выполнение из исходного кода в текущем каталоге:
    dotnet run

    Для более сложных решений может потребоваться дополнительная адаптация кода. Под .NET Core это сделать удобней и проще. Писать и собирать код вполне можно в Visual Studio под Windows.
    Ответ написан
    4 комментария
  • Как управлять состоянием полей обьекта через атрибуты?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Используйте BindingFlags:
    var managementsItems = this.GetType().GetMembers
    (
      BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public
    ).Where(m => Attribute.IsDefined(m, typeof(HideAttribute))).ToList();
    Ответ написан
    Комментировать
  • Как найти и заменить второе вхождение?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Примерно так:
    sed ':a;N;$!ba;s/""/"world"/2'

    , где двоеточие - определение метки с именем a;
    N - добавить новую строку к pattern space;
    $ - к последней строке;
    ! - применить;
    b - переход к метке, в данном случае к метке a;
    s - поиск и замена;
    /""/ - что ищем, в данном случае пустые кавычки;
    "world" - на что заменить найденное совпадение, в данном случае на "world";
    /2 - замена второго совпадения.

    echo "hello: \"\"
    hello: \"\"
    hello: \"\"" | sed ':a;N;$!ba;s/""/"world"/2'

    Еще можно такой вариант попробовать:

    sed '2s/""/"world"/1'
    Ответ написан
    4 комментария
  • С чего начать обучение C# для разработки софта под соц.сети и дальнейшей работы с API этих соц.сетей?

    AlekseyNemiro
    @AlekseyNemiro
    full-stack developer
    Работа с API - это просто веб-запросы.

    Подготовка запросов и обработка ответов - это в большинстве своем сериализация/десериализация, в основном JSON-данных, реже XML.

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

    По работе с API социальных сетей лучше читать официальную документацию.

    У меня есть библиотека для авторизации по протоколу OAuth (используется многими, если не всеми, социальными сетями), которая помимо прочего, имеет унифицированные механизмы работы с API. Посмотреть на работу библиотеки можно по следующей ссылке: demo-oauth.nemiro.net

    Для многих крупных проектов (сайтов) можно найти готовые узкопрофильные решения.

    Ниже представлен небольшой пример использования библиотеки Nemiro.OAuth в проекте Windows Forms для авторизации через Instagram и использование полученного маркера доступа для загрузки списка последних изображений текущего пользователя. Изображения загружаются в ImageList и затем выводятся в ListView:
    using System;
    using System.Drawing;
    using System.Net.Http;
    using System.Windows.Forms;
    using Nemiro.OAuth;
    using Nemiro.OAuth.LoginForms;
    
    namespace InstagramWinForms
    {
    
      public partial class Form1 : Form
      {
    
        // базовый адрес API
        private const string API_BASE_URL = "https://api.instagram.com/v1";
    
        // элемент для хранения полученных изображений
        private ImageList ImageList = new ImageList();
    
        // элемент для вывода изображений
        private ListView ListView1 = new ListView();
    
        private string AccessToken;
    
        public Form1()
        {
          InitializeComponent();
    
          // размер изображений 150x150px, 16bit
          this.ImageList.ImageSize = new Size(150, 150);
          this.ImageList.ColorDepth = ColorDepth.Depth16Bit;
    
          // настраиваем список для вывода
          this.ListView1.View = View.LargeIcon;
          this.ListView1.LargeImageList = this.ImageList;
    
          this.ListView1.Dock = DockStyle.Fill;
    
          // добавляем список на форму
          this.Controls.Add(this.ListView1);
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
          // запрос на получение маркера доступа
          this.GetAccessToken();
        }
    
        private void GetAccessToken()
        {
          // создаем форму для Instagram
          // ВНИМАНИЕ: используйте собственный идентификатор и ключ
          // получить идентификатор и ключ можно на сайте instagram:
          // https://www.instagram.com/developer/clients/manage/
          var login = new InstagramLogin
          (
            // client id вашего приложения
            "9fcad1f7740b4b66ba9a0357eb9b7dda", 
            // client key вашего приложения
            "3f04cbf48f194739a10d4911c93dcece", 
            // требуется адрес возврата, 
            // можно использовать указанный, 
            // но лучше сделать свой
            "http://oauthproxy.nemiro.net/",
            // права доступа
            // https://www.instagram.com/developer/authorization/
            // для public_content (и возможно других) убедитесь, 
            // что в настройках приложения (на сайте instagram) 
            // в разделе Permissions нет никаких требований 
            // (если требования есть, то чтобы все работало, 
            // нужно их удовлетворить :-) ...)
            scope: "basic public_content",
            // требуем получить данные профиля пользователя
            loadUserInfo: true
          );
    
          // привязываем форму авторизации к текущей форме
          login.Owner = this;
    
          // показываем форму
          login.ShowDialog();
    
          if (login.IsSuccessfully)
          {
            // все прошло успешно, запоминаем маркер доступа
            this.AccessToken = login.AccessToken.Value;
    
            // выводим в заголовок текущей формы имя пользователя
            this.Text = (login.UserInfo.DisplayName ?? login.UserInfo.UserName);
    
            // получаем изображения
            this.GetRecentMedia();
          }
          else
          {
            MessageBox.Show("Error...", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
          }
        }
    
        private void GetRecentMedia()
        {
          // отправляем запрос на получение изображений
          OAuthUtility.GetAsync
          (
            String.Format
            (
              "{0}/users/self/media/recent?access_token={1}", 
              API_BASE_URL, 
              this.AccessToken
            ),
            // результат запроса будет передан в метод GetRecentMedia_Result
            callback: GetRecentMedia_Result
          );
        }
    
        private async void GetRecentMedia_Result(RequestResult result)
        {
          if (result.StatusCode == 200)
          {
            // получили успешный ответ
            // обрабатываем его
            foreach (UniValue item in result["data"])
            {
              // загружаем текущую картинку
              using (var client = new HttpClient())
              {
                var s = await client.GetStreamAsync(item["images"]["thumbnail"]["url"].ToString());
    
                // добавляем изображение в список
                Invoke(new Action(() => this.ImageList.Images.Add(Image.FromStream(s))));
              }
    
              // создаем элемент для вывода в список 
              var image = new ListViewItem();
              // название изображения
              image.Text = item["caption"]["text"].ToString();
              // индекс изображения в списке (ImageList)
              image.ImageIndex = this.ImageList.Images.Count - 1;
    
              // добавляем элемент в список
              Invoke(new Action(() => this.ListView1.Items.Add(image)));
            }
          }
          else
          {
            this.ShowError(result);
          }
        }
    
        private void ShowError(RequestResult result)
        {
          if (result["meta"]["error_message"].HasValue)
          {
            MessageBox.Show
            (
              result["meta"]["error_message"].ToString(), 
              "Error", 
              MessageBoxButtons.OK, 
              MessageBoxIcon.Error
            );
          }
          else
          {
            MessageBox.Show
            (
              result.ToString(), 
              "Error", 
              MessageBoxButtons.OK, 
              MessageBoxIcon.Error
            );
          }
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          this.GetRecentMedia();
        }
    
      }
    
    }

    preview.gif?raw=true
    Код проекта можно найти по следующей ссылке:
    https://github.com/alekseynemiro/nemiro.oauth.dll/...
    Ответ написан
    2 комментария