01.06.08
Tags: .Net 2.0, Программирование / 4:18 pm , Victor Laskin
Оказывается метод, который возвращает список директорий (GetDirectories) иногда может их не сортировать. Вроде как это происходит на винтах под FATом. Поэтому если Вы где-то визуализируете список директорий, то рекомендую Вам вставить туда алгоритм ручной сортировки, ибо сделать это легко с помощью Array.Sort:
DirectoryInfo[] dirs = dir.GetDirectories();
//Сортировочка:
Array.Sort(dirs, 0, dirs.Length, new DirectorySort());
Сам принцип сортировки нужно оформить ввиде класса реализующего интерфейс IComparer:
class DirectorySort : System.Collections.IComparer
{
public int Compare(object x, object y)
{
DirectoryInfo d1 = x as DirectoryInfo;
DirectoryInfo d2 = y as DirectoryInfo;
return String.Compare(d1.Name, d2.Name, true, CultureInfo.CurrentCulture);
}
}
Сортировка тут не различает заглавные-прописные буквы и учитывает CurrentCulture.
Direct link
08.05.08
Tags: .Net 2.0, Программирование / 3:07 pm , Victor Laskin
В любой книжке по шарпу рассказывают о том, что такое сериализация объектов. Напомню сериализация - это просто сохранение всех свойств объекта, например, на жесткий диск для последующей загрузки (десериализации) и использования в дальнейшем. Достаточно написать волшебное слово
[Serializable]
перед описанием объекта, и его уже можно легко сохранить используя класс BinaryFormatter из System.Runtime.Serialization. Казалось бы все просто и чего еще можно хотеть… Рассмотрим ситуацию когда ваш объект изменяется в процессе написания новых версий программы. Вы добавите новое свойство и обнаружите, что чтение (десериализация) старых данных перестало работать, так как объект изменился. Можно управлять десериализацией вручную, однако это накладно.
Так вот, чтобы избавиться от этих проблем можно написать свой [де]сериализатор используя Reflection:
private static void WriteObject(object obj, StreamWriter writer)
{
Type t = obj.GetType();
PropertyInfo[] pi = t.GetProperties();
writer.WriteLine(Begin(t.Name));
//Store all props
foreach (PropertyInfo p in pi)
writer.WriteLine(FormXmlLine(p.Name, p.GetValue(obj, null).ToString()));
writer.WriteLine(End(t.Name));
}
private static string Begin(string name)
{
return “<” + name + “>”;
}
private static string End(string name)
{
return “</” + name + “>”;
}
private static string FormXmlLine(string name, string value)
{
return “ <” + name + “>” + value + “</” + name + “>”;
}
Метод просто записывает значения всех свойств объекта в формате XML. Его можно легко расширить для сохранения вложенных объектов и коллекций, добавив проверку типа свойства и видоизменив к рекуррентному виду. Хотя это не всегда нужно.
Прочитать сохраненный объект можно так:
//Lets read
public static void ReadObject(string filename, object Obj)
{
Type ObjType = Obj.GetType();
using (XmlReader reader = XmlReader.Create(filename))
{
while (reader.Read())
{
if (reader.IsStartElement())
{
if (reader.Name == ObjType.Name)
{
//Do nothing!
}
else
{
PropertyInfo[] pi = ObjType.GetProperties();
foreach (PropertyInfo p in pi)
if (p.Name == reader.Name)
{
reader.Read();
//Read the text content of the element.
if (p.PropertyType.Name == “String”)
p.SetValue(Obj, reader.ReadString(), null);
if (p.PropertyType.Name == “Int32″)
p.SetValue(Obj, reader.ReadContentAsInt(), null);
if (p.PropertyType.Name == “Int64″)
p.SetValue(Obj, reader.ReadContentAsInt(), null);
if (p.PropertyType.Name == “Long”)
p.SetValue(Obj, reader.ReadContentAsLong(), null);
}
}
}
}
}
}
Дополнив это дело нужными типами данных и проверкой ошибок, можно легко сохранять и читать объекты. Но, главное, теперь классы сохраняемых объектов можно видоизменять не заботясь о сериализации. Понятно, что формат XML можно заменить любым другим по вкусу и сохранять не на диск, а в базу данных.
Direct link
03.05.08
Tags: .Net 2.0, Программирование / 12:42 pm , Victor Laskin

Кто не в курсе, Flickr - это очень популярный хостинг фото и видео. Википедия утверждает, что в нем более 2 биллионов изображений. Ко всему этому богатству можно получить доступ из вашего .net приложения.
Самая сложная часть - это авторизация.
- Сначала Вам нужно зарегистрироваться на сервере. (как не странно
)
- Затем нужно получить ключи тут. Это две строчки - ApiKey и Secret, которые будут использоваться в вашем коде для получения доступа к сервису фликр (но не к вашему акаунту).
- Нужно скачать библиотечку Flickr.Net
- Подключив скачанную библиотеку (using FlickrNet;), Вы уже можете получить доступ к публичному контенту фликра, который доступен без авторизации.
flickr = new Flickr(ApiKey, SharedSecret);
- Но чтоб получить доступ к аккаунту нужно проделать еще одну операцию - получить Token.
tempFrob = flickr.AuthGetFrob();
string flickrUrl = flickr.AuthCalcUrl(tempFrob, AuthLevel.Write);
System.Diagnostics.Process.Start(flickrUrl);
Этот код запустит браузер, в котором пользователь должен подтвердить, что дает доступ вашему софту.
- Только теперь можно получить полный доступ:
Auth auth = flickr.AuthGetToken(tempFrob);
flickr.AuthToken = auth.Token;
- Полученный токен можно сохранить и использовать для быстрой авторизации в дальнейшем:
flickr = new Flickr(ApiKey, SharedSecret, Token);
- Теперь можно загрузить парочку фотографий:
string photoId = flickr.UploadPicture(file, title, descripton, tags);
Из бонусов механизма подобной авторизации можно отметить возможность просмотра статистики использования ApiKey, то есть вашего софта, которую можно найти там же, где вы получали ключи.
Что касается самого сервиса - обнаружил, что есть серьезное ограничение на размер фото, что меня лично, как любителя лучшего качества, не устраивает.
Напоследок - моя страница на фликре
Direct link
18.04.08
Tags: .Net 2.0, Программирование / 5:39 pm , Victor Laskin
Нашел на одном из западных блогов очень удобную библиотеку для работы с фтп.
Чтоб загрузить файл на свой сервер достаточно написать пару строк:
using BytesRoad.Net.Ftp;
…
string FtpServer = “my.server.ru”;
string Username = “username”;
string Password = “password”;
string RemotePath = “\\folderonserver/”;
public void UploadFile(string LocalFile)
{
// get instance of the FtpClient
FtpClient client = new FtpClient();
// use passive mode
client.PassiveMode = true;
client.Connect(Timeout, FtpServer, 21);
client.Login(Timeout, Username, Password);
// build the target file path
string target = System.IO.Path.Combine(RemotePath,
System.IO.Path.GetFileName(LocalFile)).Replace(“\\”, “/”);
// synchronously upload the file
client.PutFile(Timeout, target, LocalFile);
//Disconnect
client.Disconnect(Timeout);
}
Обратите внимание, что используется passive mode.
Библиотека распространяется по лицензии GPL, то есть бесплатно. Скачать можно отсюда.
Direct link
10.02.08
Tags: .Net 2.0, Программирование / 9:33 pm , Victor Laskin
Всякий раз, когда я пользовался Math.Min() или Math.Abs(), я думал о том, а не лучше было бы написать эти операции простым неравенством. Наконец, я решил просто написать небольшой тестик, который должен раз и навсегда расставить все на свои места.
В качестве основы я взял почти пустой цикл:
int N = 100000000;
Start = DateTime.Now;
//Almost nothing!
for (int i = -N; i < N; i++)
result = i;
End = DateTime.Now;
Почти пустой для того чтоб компилятор не сделал каких нить слишком умных действий по его оптимизации. В первую очередь испытанию подверглась функция вычисления модуля числа. Реализовать эту простую операцию можно так:
for (int i = -N; i < N; i++)
{
result = i;
result = Math.Abs(i);
}
или, например, так:
for (int i = -N; i < N; i++)
{
result = i;
result = (i >= 0) ? i : -i;
}
Из времени выполнения этих циклов я вычел время выполнения пустого цикла. Получились интересные результаты:
Read more »
Direct link
28.01.08
Tags: .Net 2.0, Программирование / 10:15 pm , Victor Laskin
Многие любят валить вину за то, что их код медленно работает, на .Net Framework. А между тем во многих случаях ситуацию можно исправить поменяв пару строк кода.
Рассмотрю практический пример функции по обработке фотографии. Есть некий цикл, который обходит все пикселы изображения и преобразует их хитрым образом.
Вначале пару слов о границах цикла. Хотя в первой версии фреймворка и были какие-то проблемы с функцией Length, то сейчас все хорошо. Главное, чтоб это не была какая-нибудь хитрая функция, которая выполняется на каждой итерации цикла и замедляет его в несколько раз.
for (i=0; i<Data.Length; i++)
{
//Обработка
}
Я вообще использую следующую конструкцию, так как цикл распараллелен на несколько ядер (пост):
int i1 = GetFirstIndex();
int i2 = GetLastIndex();
for (i=i1; i<=i2; i++)
{
//Обработка
}
Далее за границы цикла стоит по возможности вынести все операции по выделению памяти. Кроме того при вызове функций внутри цикла, по возможности нельзя дублировать данные, особенно массивы.
Пример плохого кода:
Read more »
Direct link
04.11.07
Tags: Книги, .Net 2.0, Программирование / 5:14 pm , Victor Laskin
Новость не нова, но в скором времени в Visual Studio будет добавлен новый язык - F#. Еще не объявлены сроки этого нововведения, но это не может не радовать.
Попробовать язык в действии можно уже сейчас. Лицензия позволяет создавать коммерческие приложения на его основе.
Описание:
F# is a variant of the ML programming language for .NET and has a core language that is similar to that of OCaml. It is a mixed functional/imperative/object-oriented programming language which is excellent for medium-advanced programmers and for teaching. In addition, you can access hundreds of .NET libraries using F#, and the F# code you write can be accessed from C# and other .NET languages. This release of F# includes a command line compiler as well as ‘F# for Visual Studio’, which provides interactive syntax highlighting, parsing, typechecking and intellisense for F# code inside Visual Studio 2003/2005/Orcas, and ‘F# Interactive’, a command-line top level environment for F#.
По языку уже написана книга: Expert F#.
Так что, возможно, у него большое будущее.
Direct link
25.10.07
Tags: .Net 2.0, Программирование / 5:36 pm , Victor Laskin
Не для кого не секрет, что ближайшее будущее за многоядерными системами. И каждый кодер уже должен быть к этому готов.
Довольно часто возникает потребность в оптимизации того или иного алгоритма. При этом обычно подобные доработки связаны с большими затратами времени и сил. Однако, с приходом многоядерных процессоров алгоритм допускающий распараллеливание может быть оптимизирован с необычайной легкостью.
Для того чтобы использовать все ядра процессора необходимо создать многопоточный алгоритм с числом потоков равным числу ядер. Обычно ядра два (Core Duo), поэтому я приведу пример для двух потоков.
Каждый поток представляет собой объект класса Thread. Во время создания потока необходимо указать точку входа - статический метод класса (Thread1Proc, Thread2Proc). Метод Start запускает поток, а Join ждет его завершения.
...
Thread t1 =
new Thread
(new ThreadStart
(Thread1Proc
));
Thread t2 =
new Thread
(new ThreadStart
(Thread2Proc
));
t1.
Start();
t2.
Start();
while ((t1.
ThreadState != ThreadState.
Stopped) &&
(t2.
ThreadState != ThreadState.
Stopped))
{
//Here we could show some info about process
Application.
DoEvents();
Thread.
Sleep(1);
}
t1.
Join();
t2.
Join();
.....
public static void Thread1Proc
()
{
//Do 1th half
}
public static void Thread2Proc
()
{
//Do 2nd half
}
Такая оптимизация позволяет поднять скорость выполнения кода в два раза! Единственная проблема, что не всегда можно разбить код на две параллельные части.
Будем ждать 128-ми ядерных систем ))
Direct link
21.09.07
Tags: SQL, .Net 2.0, Программирование / 2:19 pm , Victor Laskin
Недавно опять столкнулся с существенной потерей производительности при использовании блока:
while (reader.Read())
{
try
{
// операции с reader.GetValue()
}
catch
{
// выставление значений по умолчанию
}
}
В этом блоке операция чтения заключена в try блок, и при любых ошибках при чтении переменным присваиваются некие значения по умолчанию. Например, если в базе данных не задано значение поля, то reader вернет null. В этом случае вылетит исключение при обработке и действие перейдет в catch блок, где можно выставить, например, числовой “0″.
Так вот, если у Вас в базе некое поле с данными еще не забито значениями, то вышеописанный код будет работать в 10 раз медленнее! Обработка исключений не дается дешево. Чтоб заставить код работать быстро в любом случае, надо учесть случаи когда выпадают наиболее часто встречаемые исключения и поставить дополнительные проверки в блоке try. Например, проверить при чтении не вернул ли reader null и сразу подменить его неким разумным значением.
Direct link
16.07.07
Tags: .Net 2.0, Программирование / 2:46 pm , Victor Laskin
[ratings]Вчера наткнулся на баг в контроле WebBrowser (.Net 2.0), позволяющим работать с интернет страницами. Я писал программку, которая анализировала код нескольких страниц некого сайта и потом, спустя некоторое время, сама выполняла некие действия на нем по таймеру. Для анализа содержимого страниц я просто использовал свойство DocumentText, которое должно возвращать хтмл код документа (аналогично кнопке View Source в IE):
string source = webBrowser1.DocumentText;
Я отлаживал программу под Vista, и там все прекрасно работало. Но когда я попробовал запустить тот же код на машине с XP, то получил эксепшен как раз на этой строчке, говорящий что контрол не может найти какой-то файл. Ошибка возникала не сразу, а после перехода между страницами на исследуемом сайте.
Поиск решения этой проблемы в интернете дал свои результаты. Оказалось, что это просто глюк контрола. И для его исправления необходимо просто поставить на систему все критические обновления, которые включают в себя Internet Explorer 7.0 и фикс безопасности для .Net 2.0, который весит аж 14 мегабайт.
Вывод: Не забывайте запускать Windows Update. 
Direct link