Начнем как водится с начала. Дадим определение понятия полиморфизм:
1. Полиморфизм (от греч. πολύ — «много» и μορφή — «форма», многообразный) в программировании — это возможность использования в одном и том же контексте различных программных сущностей (объектов, типов данных и т. д.) с одинаковым интерфейсом. (Журнал Функциональное программирование).
2. Полиморфи́зм — взаимозаменяемость объектов с одинаковым интерфейсом (Википедия).
3. Полиморфизм — это механизм позволяющий вызывать методы классов объектов, а не классов объектных переменных, ссылающихся на эти объекты (ваш покорный слуга).
среда, 6 января 2010 г.
Позднее связывание
Наверно из всех тем связанных с ООП тема позднего связывания является одной из самых тяжелых для понимания. В связи с этим, я хотел бы рассмотреть три механизма позднего связывания более предметно. Рассматривать я их буду в следующем порядке:
1. Полиморфизм
2. Делегаты / события
3. Reflection (отражение)
Начну с того, что я буду вкладывать в понятие "позднее связывание".
Позднее связывание это механизм позволяющий отложить принятие решения о том, какой код будет выполняться в данном месте программы на время более позднее, чем написание именно этого фрагмента кода. Когда будет приниматься решение? Да когда угодно! Когда другой программист использует ваш код в своем коде, или когда выполняется программа содержащая ваш код. Т.е. решение принимается гарантированно после того, как вы нажали Ctrl+Shift+B.
1. Полиморфизм
2. Делегаты / события
3. Reflection (отражение)
Начну с того, что я буду вкладывать в понятие "позднее связывание".
Позднее связывание это механизм позволяющий отложить принятие решения о том, какой код будет выполняться в данном месте программы на время более позднее, чем написание именно этого фрагмента кода. Когда будет приниматься решение? Да когда угодно! Когда другой программист использует ваш код в своем коде, или когда выполняется программа содержащая ваш код. Т.е. решение принимается гарантированно после того, как вы нажали Ctrl+Shift+B.
вторник, 5 января 2010 г.
Привязка к данным в своих UC
Всех с Новым 2010 годом :)
В декабре уже ушедшего 2009 года было много студентов, работы, опять же пожготовка к новому году, поэтому даже на 1 публикацию вемени не было :( А вот сейчас много выходных, сессия и все такой, поэтому буду наверстывать.
Сегодня я хотел бы поговорить о биндинге внешних данных к нашим UserControl (или CustomControl, кому как больше нравится).
В декабре уже ушедшего 2009 года было много студентов, работы, опять же пожготовка к новому году, поэтому даже на 1 публикацию вемени не было :( А вот сейчас много выходных, сессия и все такой, поэтому буду наверстывать.
Сегодня я хотел бы поговорить о биндинге внешних данных к нашим UserControl (или CustomControl, кому как больше нравится).
среда, 25 ноября 2009 г.
Тестовые данные в SketchFlow
Сегодня поговорим о том, как в SketchFlow проекте показать тестовые данные.
Пусть необходим список сотрудников, при клике на конкретном сотруднике открывается более подробная информация.
Пусть необходим список сотрудников, при клике на конкретном сотруднике открывается более подробная информация.
понедельник, 23 ноября 2009 г.
Создание окна из потока отличного от потока диспетчера приложения
Возникла задача, в процессе вызова метода из workflow показать форму для ввода дополнительных данных (для тех, кто не в курсе - workflow выполняются в отдельном потоке, и соответственно если метод вызывается из workflow, он тоже выполняется в этом потоке). Приложение написано на WPF. Привычная последовательность действий:
Выполнялось, но форма не появлялась :(
Пришлось пойти на следующее ухищрение:
А вот теперь все работает ;)
public void StartReadFromScala(Guid idWorkflow)
{
WndReadFromScala form = new WndReadFromScala();
form.Show();
}
* This source code was highlighted with Source Code Highlighter.
Выполнялось, но форма не появлялась :(
Пришлось пойти на следующее ухищрение:
public void StartReadFromScala(Guid idWorkflow)
{
// Создаем форму для ввода данных, но создаем ее в главном потоке
Application.Current.Dispatcher.Invoke(new NoParamHandler(CreateWndReadFromScala), new object[] { });
}
private void CreateWndReadFromScala()
{
WndReadFromScala form = new WndReadFromScala();
form.Show();
}
* This source code was highlighted with Source Code Highlighter.
А вот теперь все работает ;)
вторник, 3 ноября 2009 г.
Олимпиада по многократному решению делемы заключенного
Было принято решение провести олимпиаду по решению многократной дилемы заключенного.
К участию приглашаются все желающие. Дата проведения олимпиады будет объявлена дополнительно. Ориентировочно олимпиада будет проходить 17 декабря 2009 года в 16:00.
Для участия необходимо предоставить dll разработанную на платформе .Net и содержащую класс потомок интерфейса:
Интерфейс добавляется в проект из сборки которую можно скачать здесь.
В процессе проведения соревнования запрещается:
1. Попытка загрузки, рефакторинга, изменения или удаления сборок оппонентов.
2. Запрещается влиять на работу сервера иными средствами кроме возвращения массива из метода MakeStep.
3. Осуществлять сговор участников соревнования.
4. Модифицировать ICompetition.dll или реализовывать интерфейс ICompetition в своих сборках.
Порядок проведения соревнования:
1. Все участники соревнования предоставляют dll удовлетворяющие описанным выше требованиям и запретам.
2. Сервер олимпиады подгружает все зарегистрированные сборки с загрузкой из каждой ОДНОГО класса потомка интерфейса ICompetition.
3. От каждого класса создается объект посредством вызова конструктора по умолчанию.
4. Для каждого созданного объекта вызывается метод SetCount в который передается количество участников соревнований.
5а. В первом туре в метод MakeStep передается null. Метод должен вернуть в виде массива bool-евых значений свое отношение к сборкам противников: true - сотрудничать, false - предавать. Количество значений в массиве должно соответствовать количеству участников полученных классом через метод SetCount.
5б. Во втором и последующих турах (проходит от 30 до 50 туров), в метод MakeStep передается отношение к данному участнику всех оппонентов. Количество значений в массиве соответствует количеству участников полученных классом через метод SetCount. На основе полученных данных необходимо вернуть массив отношения к сборкам противников.
6. Через 5 секунд после вызова соответствующих методов, все методы не закончившие обработку и не вернувшие значение снимаются с соревнований.
7. Если количество туров превысило 30 и сгенерированное случайное число меньше 1/20 то соревнование заканчивается, в противном случае переход в пункт 5б.
Если два участника поставили взаимное true, то каждый из них получает по 7 очков рейтинга. Если два участника поставили взаимное false, то каждый из них получает по 3 очка рейтинга. Если один из участников поставил true в ответ на false другого участника, то первый не получает очки рейтинга, а второй получает 10 очков рейтинга.
Пять программ набравших наибольшее количество баллов рейтинга получают по 5,4,3,2 и 1 очку в зависимости от занятого места.
Соревнования повторяются 3-5 раз. Программа набравшая суммарно максимальное количество очков признается победителем олимпиады.
В качестве приза будет нечто полезное программистам ;)
Удачной олимпиады.
P.s. В случае обнаружения неточностей, ошибок или при наличии предложений писать в комментариях.
К участию приглашаются все желающие. Дата проведения олимпиады будет объявлена дополнительно. Ориентировочно олимпиада будет проходить 17 декабря 2009 года в 16:00.
Для участия необходимо предоставить dll разработанную на платформе .Net и содержащую класс потомок интерфейса:
namespace Competition
{
public interface ICompetition
{
/// <summary>
/// Передает в библиотеку количество участников
/// </summary>
/// <param name="p_count">количество участников</param>
void SetCount(int p_count);
/// <summary>
/// Делает один ход
/// </summary>
/// <param name="p_prevResult">Массив предыдущих ответов соответствующих участников</param>
/// <returns>Массив ответов на текущем шаге</returns>
bool[] MakeStep(bool[] p_prevResult);
}
}
* This source code was highlighted with Source Code Highlighter.
Интерфейс добавляется в проект из сборки которую можно скачать здесь.
В процессе проведения соревнования запрещается:
1. Попытка загрузки, рефакторинга, изменения или удаления сборок оппонентов.
2. Запрещается влиять на работу сервера иными средствами кроме возвращения массива из метода MakeStep.
3. Осуществлять сговор участников соревнования.
4. Модифицировать ICompetition.dll или реализовывать интерфейс ICompetition в своих сборках.
Порядок проведения соревнования:
1. Все участники соревнования предоставляют dll удовлетворяющие описанным выше требованиям и запретам.
2. Сервер олимпиады подгружает все зарегистрированные сборки с загрузкой из каждой ОДНОГО класса потомка интерфейса ICompetition.
3. От каждого класса создается объект посредством вызова конструктора по умолчанию.
4. Для каждого созданного объекта вызывается метод SetCount в который передается количество участников соревнований.
5а. В первом туре в метод MakeStep передается null. Метод должен вернуть в виде массива bool-евых значений свое отношение к сборкам противников: true - сотрудничать, false - предавать. Количество значений в массиве должно соответствовать количеству участников полученных классом через метод SetCount.
5б. Во втором и последующих турах (проходит от 30 до 50 туров), в метод MakeStep передается отношение к данному участнику всех оппонентов. Количество значений в массиве соответствует количеству участников полученных классом через метод SetCount. На основе полученных данных необходимо вернуть массив отношения к сборкам противников.
6. Через 5 секунд после вызова соответствующих методов, все методы не закончившие обработку и не вернувшие значение снимаются с соревнований.
7. Если количество туров превысило 30 и сгенерированное случайное число меньше 1/20 то соревнование заканчивается, в противном случае переход в пункт 5б.
Если два участника поставили взаимное true, то каждый из них получает по 7 очков рейтинга. Если два участника поставили взаимное false, то каждый из них получает по 3 очка рейтинга. Если один из участников поставил true в ответ на false другого участника, то первый не получает очки рейтинга, а второй получает 10 очков рейтинга.
Пять программ набравших наибольшее количество баллов рейтинга получают по 5,4,3,2 и 1 очку в зависимости от занятого места.
Соревнования повторяются 3-5 раз. Программа набравшая суммарно максимальное количество очков признается победителем олимпиады.
В качестве приза будет нечто полезное программистам ;)
Удачной олимпиады.
P.s. В случае обнаружения неточностей, ошибок или при наличии предложений писать в комментариях.
суббота, 3 октября 2009 г.
Сервис постоянства в Workflow Foundation
Для одного маленького, но очень интересного проекта решили применить workflow. И сразу необходимо было решить задачу сохранения работающих workflow во внешних хранилищах между запусками клиентских приложений.
В русскоязычном интернете этой проблеме уделено весьма мало внимания... Где можно почитать? Я нашел вот эти работы: на rsdn, gotdotnet и т.д..
Эти статьи либо достаточно поверхностны, либо подразумевают (как последняя) что вы уже все знаете :).
Поэтому давайте попробуем решить поставленную задачу (сохранение workflow во внешнем хранилище) медленно и по шагам.
Итак, для решения данной задачи нам понадобится VS 2008 + MS SQL (версия последнего не особенно принципиальна).
1. Идем сюда и читаем как нам подготовить MS SQL.
2. Создаем простенький workflow на котором будем ставить эксперименты. Для простоты я воспользовался следующим:

Первое состояние стартовое и мы его сразу покидаем. Второе вызывает метод Print из нижеописанного интерфейса и ждет событие из него же. Третье служит для того чтобы сказать что событие успешно получено и обработано.
Обещанный интерфейс:
2. Тестировать будем при помощи формы следующего вида:

Кнопки 2 и 3 создают WorkflowRuntime и все необходимые сервисы, а кроме того кнопка 2 создает экземпляр workflow.
Как видим из метода 2 кнопки Id workflow выводится в textBox.
Кнопка 1 отправляет событие в workflow идентификатор которого берет из поля формы:
А вот кнопка 4 отправляет событие в workflow чей идентификатор берется из textBox-а.
В чем отличие? Если в textBox попадает тот же идентификатор что хранится в поле _instance? смотрим следующий шаг!
3. Запускаем приложение и тестируем работу workflow кликнув на кнопке 2, а затем 1. Поток отрабатывает как и ожидалось, в чем мы можем убедится за счет вызова метода Print например такого содержания:
А теперь самое интересное! Перезапускаем приложение нажимаем на кнопку 2, копируем в буфер обмена значение идентификатора и?..

Перезапускаем приложение!
В новой копии приложения создаем рунтайм (но не workflow) кнопкой 3. Вставляем из буфера в textBox идентификатор. Нажимаем на кнопку 4 и видем в label подтверждение обработки события в workflow.

Или иными словами созданный workflow был успешно сохранен во внешнем хранилище, а при повторном запуске приложения и попытке отправить ему события извлечен из оного. Что собственно говоря и требовалось по условию задачи.
На этом можно бы и закончить, но рекомендую попробовать написать все это самостоятельно ручками ;)
В русскоязычном интернете этой проблеме уделено весьма мало внимания... Где можно почитать? Я нашел вот эти работы: на rsdn, gotdotnet и т.д..
Эти статьи либо достаточно поверхностны, либо подразумевают (как последняя) что вы уже все знаете :).
Поэтому давайте попробуем решить поставленную задачу (сохранение workflow во внешнем хранилище) медленно и по шагам.
Итак, для решения данной задачи нам понадобится VS 2008 + MS SQL (версия последнего не особенно принципиальна).
1. Идем сюда и читаем как нам подготовить MS SQL.
2. Создаем простенький workflow на котором будем ставить эксперименты. Для простоты я воспользовался следующим:

Первое состояние стартовое и мы его сразу покидаем. Второе вызывает метод Print из нижеописанного интерфейса и ждет событие из него же. Третье служит для того чтобы сказать что событие успешно получено и обработано.
Обещанный интерфейс:
[ExternalDataExchangeAttribute()]
public interface IMethodAndEvents
{
event EventHandler<ExternalDataEventArgs> MyEvent;
void PrintText(string p_text);
}
* This source code was highlighted with Source Code Highlighter.
2. Тестировать будем при помощи формы следующего вида:

Кнопки 2 и 3 создают WorkflowRuntime и все необходимые сервисы, а кроме того кнопка 2 создает экземпляр workflow.
private void button2_Click(object sender, RoutedEventArgs e)
{
button3_Click(null, null);
_instance = _runtime.CreateWorkflow(typeof(Workflow1));
_instance.Start();
textBox1.Text = _instance.InstanceId.ToString();
}
private void button3_Click(object sender, RoutedEventArgs e)
{
_runtime = new WorkflowRuntime();
// Create the SqlWorkflowPersistenceService.
string connectionString = "Initial Catalog=WorkflowPersistenceStore;Data Source=localhost;Integrated Security=SSPI;";
bool unloadOnIdle = true;
TimeSpan instanceOwnershipDuration = TimeSpan.MaxValue;
TimeSpan loadingInterval = new TimeSpan(0, 2, 0);
SqlWorkflowPersistenceService persistService = new SqlWorkflowPersistenceService(connectionString, unloadOnIdle, instanceOwnershipDuration, loadingInterval);
_runtime.AddService(persistService);
ExternalDataExchangeService externalDataExchangeService = new ExternalDataExchangeService();
_runtime.AddService(externalDataExchangeService);
externalDataExchangeService.AddService(this);
_runtime.StartRuntime();
}
* This source code was highlighted with Source Code Highlighter.
Как видим из метода 2 кнопки Id workflow выводится в textBox.
Кнопка 1 отправляет событие в workflow идентификатор которого берет из поля формы:
private void button1_Click(object sender, RoutedEventArgs e)
{
if (MyEvent != null)
{
MyEvent(null, new ExternalDataEventArgs(_instance.InstanceId));
}
}
* This source code was highlighted with Source Code Highlighter.
А вот кнопка 4 отправляет событие в workflow чей идентификатор берется из textBox-а.
private void button4_Click(object sender, RoutedEventArgs e)
{
if (MyEvent != null)
{
Guid id = new Guid(textBox1.Text);
MyEvent(null, new ExternalDataEventArgs(id));
}
}
* This source code was highlighted with Source Code Highlighter.
В чем отличие? Если в textBox попадает тот же идентификатор что хранится в поле _instance? смотрим следующий шаг!
3. Запускаем приложение и тестируем работу workflow кликнув на кнопке 2, а затем 1. Поток отрабатывает как и ожидалось, в чем мы можем убедится за счет вызова метода Print например такого содержания:
delegate void PrintHandler(string p_text);
public void PrintText(string p_text)
{
// Проверяем совпадает ли поток диспетчера с потоком вызвавшим метод
if (Dispatcher.Thread == Thread.CurrentThread)
{
// Все замечательно :) меняем значение textbox-а
label1.Content = p_text;
}
else
{
// Нет :( все плохо :( перезапускаем метод в потоке диспетчера
Dispatcher.Invoke(new PrintHandler(PrintText), new object[] { p_text });
}
}
* This source code was highlighted with Source Code Highlighter.
А теперь самое интересное! Перезапускаем приложение нажимаем на кнопку 2, копируем в буфер обмена значение идентификатора и?..

Перезапускаем приложение!
В новой копии приложения создаем рунтайм (но не workflow) кнопкой 3. Вставляем из буфера в textBox идентификатор. Нажимаем на кнопку 4 и видем в label подтверждение обработки события в workflow.

Или иными словами созданный workflow был успешно сохранен во внешнем хранилище, а при повторном запуске приложения и попытке отправить ему события извлечен из оного. Что собственно говоря и требовалось по условию задачи.
На этом можно бы и закончить, но рекомендую попробовать написать все это самостоятельно ручками ;)
Подписаться на:
Сообщения (Atom)