Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

№40 рассылки '.Net Собеседник':


Информационный Канал Subscribe.Ru

.Net Собеседник #40

Содержание
  1. От автора
  2. Обзор новостей
  3. Обработка списков с использованием yield и делегатов
  4. Время кода - Отлавливаем обновление страницы
  5. Форумы .Net на www.sql.ru

От автора

Здравствуйте, коллеги!

В качестве единоразавой рекламной акции с целью привлечения большего количества читателей электронная версия второго номера журнала "Алгоритм" выложена для скачивания по адресу - часть 1, часть 2, часть 3. Общий размер архива около 1МБ, архиватор - Rar версии 3.0 и выше.
Также снижена цена на подписку журнала в электронном виде (с третьего номера) - теперь он стоит $1/27 руб./5 грн. Как подписаться - подробнее смотрите на сайте.
На этом всё - желаю интересного чтения.

{К содержанию}

Обзор новостей

  1. Вышел VG.net 2.4: анимированная векторная графика для .NET
    VG.NET – ядро векторной графики для .NET, включающее графический дизайнер, интегрированный в Visual Studio. С версии 2.4 можно создавать текстовые объекты, позиционированные относительно точки, обводить текст, интегрировать свой код отрисовки в класс CustomElement, работать внутри групп в новом режиме Active Group.
  2. Вышел Likemedia ClassBuilder - версия 3.7
    Новая версия известного генератора кода.
  3. Передовая технология построения GUI для .NET.
    9Rays.Net объявила о выходе версии Beta1 нового революционного продукта в области инструментов и графических компонентов для .NET Instrumentation Model Kit. Этот продукт специально разработан для существенного упрощения и оптимизации процесса создания пользовательского интерфейса.
  4. Провайдер веб-сервисов Elementool мигрировал на Microsoft ASP .NET
    Elementool, провайдер веб-инструментов управления проектами, в 10 раз улучшил производительность своих решений после перехода на технологию Microsoft's ASP .NET, подробнее здесь: www.elementool.com.

{К содержанию}

Статья номера

Обработка списков с использованием yield и делегатов

ЯЗЫК: C#
Автор статьи: Marcus Andrйn

ПЕРЕВОД: Чужа В.Ф. ака hDrummer
КОД К СТАТЬЕ: ListProcessing_src_new.zip

Вступление

В этой статье описывается, каким образом можно использовать итераторы для обработки списков, реализующих интерфейс IEnumerable. Этот метод не так часто используется в таких языках, как c#, java, так что будет интересно посмотреть, как он работает. Поскольку код использует yield, а также анонимные делегаты, то работать будет только в версии c# 2.0

Простой метод yield (итератор)

class PositiveNumbers : System.Collections.IEnumerable
{
  public System.Collections.IEnumerator GetEnumerator()
  {
    int a = 1;
    while (true)
    {
      yield return a;
      a = a + 1;
    }
  }
}

...

foreach (int num in new PositiveNumbers())
{
//Что-то делаем с каждым положительным числом ..
}

     Вместо написания класса, реализующего три метода, возвращающих IEnumerator, мы можем в c# 2.0 написать один метод, использующий yield. Доступ к этому методу может быть осуществлён через методы IEnumerator - MoveNext, Reset, Current. (Кстати: yield не поддерживает Reset).
     Так как это всё работает? Ответ прост. Сначала вызывается MoveNext, наш метод работает с самого начала. Переменная a устанавливается в 1, мы входим в цикл while и возвращаем a равный 1. В следующий раз, при вызове MoveNext, мы продолжаем со строки после yield, a=a+1, что увеличивает a до 2, мы делаем ещё один шаг в цикле и вызываем yield return. Следующий код продемонстрирует это более чётко.

public System.Collections.IEnumerator GetEnumerator()
{
  yield return "First element";
  yield return "Second element";
  yield return "Third element";
  yield return "Last element";
}

Этот метод yield (итератор) представляет собой список, всегда содержащий четыре строковых элемента.

Немного синтаксического сахара

Проблема с вышеприведенным подходом заключается в том, что нам нужно по одному классу для каждог итератора. К счастью, в c# 2.0 есть решение для этого. Если yield помещён в метод, возвращающий IEnumerable, то компилятор всё сделает за вас.

class Iterators
{
  public static System.Collections.IEnumerable PositiveNumbers()
  {
    int a = 1;
    while (true)
    {
      yield return a;
      a = a + 1;
    }
  }
}

Это значит не только то, что мы можем разместить несколько итераторов в классе. Теперь мы получаем доступ к каждому итератору посредством класса и имени метода, вместо того, чтобы использовать оператор new.

foreach (int num in IteratorsPositiveNumbers()){}

Наконец, наш итератор возвращает только целые, т.е. мы можем его оптимизировать путём использования шаблонной версии IEnumerable. Небольшое изменение в заголовке метода увеличит скорость его исполнения и уменьшит количество необходимых приведений к типу.

public static System.Collections.Generic.IEnumerable PositiveNumbers()

Превращаем бесконечный список в конечный

Перечислитель PositiveNumbers, приведенный выше, работает бесконечно. А если нам нужны только некоторые положительные числа? Решение – добавить ещё один итератор. Он будет иметь три аргумента. Индекс первого желаемого элемента, последнего и Ienumerable, содержащий исходный список.

public static System.Collections.IEnumerable SubList(int start, int end, IEnumerable enumerable)
{
  int count = 0;
  foreach (object o in enumerable)
  {
    count++;
    if (count < start)
      continue;
    else if (count <= end)
      yield return o;
    else
      yield break;
  }
}

...

//это даёт нам список, содержащий элементы от 5 до 15
IEnumerable numbers = Iterators.SubList(5, 15, Iterators.PositiveNumbers()));

Наш итератор просто пропускает элементы в списке до тех пор, пока мы не наткнёмся на пятый элемент. Потом мы делаем yield return до появления 16-го элемента. Тут вызывается yield break;. Что равносильно утверждению о том, что в коллекции не осталось элементов.

Отображение

Последний итератор, который мы изучим, получил своё название от функции из языка LISP. Что он делает? Просто берёт метод и список. А потом возвращает список, содержащий элементы, к которым применён взятый метод.

public delegate object MapFunction(object o);

///
/// Запускаем эту функцию для каждого элемента списка
///

  public static IEnumerable Map(MapFunction mapFunction, IEnumerable enumerable)
  {
    foreach (object o in enumerable)
    {
      yield return mapFunction(o);
    }
  }

...

foreach (int num in
        I.Map(
// умножаем каждый элемент на 2
        delegate(object o){  return ((int)o) * 2; },
        I.SubList(5, 15, I.PositiveNumbers())))
    {
      Console.Write("{0} ", num); //Печатает 10 12 14 .. 28 30
    }

Код прост. Мы просто вызываем MapFunction для каждого объекта и возвращаем результат с помощью yield return.

И наконец…

Хотя всё, что приведено в этой статье, можно решить и другим путём, интересно пронаблюдать, как всё это работает со стороны функционального программирования. Особенно интересно посмотреть, как мы обращаемся со списками, содержащими все положительные числа, генерируя элементы по требованию, делая возможным использование бесконечных списков.

{К содержанию}

Время кода

Отлавливаем обновление страницы

ЯЗЫК: VB.Net
Автор статьи: Altaf Al-Amin

ПЕРЕВОД: Чужа В.Ф. ака hDrummer
КОД К СТАТЬЕ: Detecting_Refresh_src.zip ~100 KB

Вступление

Общей проблемой, с которой сталкиваются все веб-разработчики, является проблема предупреждения обновления выведенной веб-страницы. Проблема возникает, если предыдущий запрос, отправденный на сервер, был PostBack, который, например, вставил данные вашей веб-формы в БД. Обновление приводит к повторной вставке и появлению дублированных записей в БД. Запретить обновлять страницу пользователю мы не можем. Так что же делать? Можно определить, что обновление произошло и как-то отреагировать на это.

Эта статья базируется на статье “Build Your ASP.NET Pages on a Richer Bedrock”, в которой Dino Esposito обрисовал механизм детектирования обновления страниц. Метод, предложенный им, слишком сложен, хотя основная идея вполне здравая и использована как основа приведенного здесь решения. Механизм, предложенный Dino, использует счётчик, хранящийся в странице и сессионную переменную, содержащую предыдущее число запросов на сервер – если они равны, то мы имеем дело с обновлением страницы.

Стратегия:

Моя стратегия заключается в использовании ViewState. Поскольку мы используем ViewState, будет логично использовать методы LoadViewState и SaveViewState. Использование именно этих двух методов, а не метода OnLoad, имеет и такое преимущество – мы избегаем потенциальных проблем с реализацией метода Page_Load у наследников страницы. Рассмотрим эти методы:

LoadViewState
Метод LoadViewState загружает предыдущий, предварительно сохранённый ViewState.
Объект savedState содержит значения для элементов страницы.
SaveViewState
Сохраняет изменения состояния серверного элемента, произошедшие с момента отправки страницы на сервер.
Возвращает текущий viewstate серверного элемента. Если такового нет, то возвращает null.

Как работает процесс

Метод LoadViewState, который является частью инициализации страницы, вызывается только во время PostBack, так что метод SaveViewState является единственным из двух, относящихся к ViewState, который вызовется при первом выводе страницы.
Кстати: _refreshState (который при первом запросе страницы равен false, а в последующих равен значению ViewState) хранится в переменной Session["__ISREFRESH"], а противоположное значение _refreshState сохраняется в новом ViewState.

Protected Overrides Function SaveViewState() As Object
        Session("__ISREFRESH") = _refreshState
        Dim AllStates() As Object = New Object(2) {}
        AllStates(0) = MyBase.SaveViewState
        AllStates(1) = Not (_refreshState)
 Return AllStates
End Function

Как только происходит событие PostBack, вызывается метод LoadViewState.

Protected Overrides Sub LoadViewState(ByVal savedState As Object)
        Dim AllStates As Object() = savedState
        MyBase.LoadViewState(AllStates(0))
        _refreshState = Boolean.Parse(AllStates(1))<br>        _isRefresh = _refreshState = Session("__ISREFRESH")
End Sub


Кстати: переменная _refreshState берётся из ViewState и сравнивается со значением в Session["__ISREFRESH"]. Результат сохраняется в _isRefresh, значение которого доступно через свойство IsRefresh. Ниже приведен весь класс:

Public Class test1
    Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "
    'следующее объявление необходимо для  Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> 
    Private Sub InitializeComponent()
    End Sub

    Protected WithEvents Button1 As System.Web.UI.WebControls.Button
    Protected WithEvents label1 As System.Web.UI.WebControls.Label
 
    'следующее объявление необходимо для Web Form Designer.

    'Не удаляйте и не перемещайте его.

    Private designerPlaceholderDeclaration As System.Object

    Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: следующий вызов необходим для Web Form Designer
        'Не изменяйте его.

        InitializeComponent()

    End Sub

#End Region

    Private _refreshState As Boolean
    Private _isRefresh As Boolean

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.label1.Text = _isRefresh.ToString
    End Sub

    Protected Overrides Sub LoadViewState(ByVal savedState As Object)
        Dim AllStates As Object() = savedState
        MyBase.LoadViewState(AllStates(0))
        _refreshState = Boolean.Parse(AllStates(1))<br>        _isRefresh = _refreshState = Session("__ISREFRESH")
    End Sub

    Protected Overrides Function SaveViewState() As Object
        Session("__ISREFRESH") = _refreshState
        Dim AllStates() As Object = New Object(2) {}
        AllStates(0) = MyBase.SaveViewState
        AllStates(1) = Not (_refreshState)
        Return AllStates
    End Function
 
End Class

     При нажатии на элемент, генерирующий отправку страницы на сервер, происходит событие LoadViewState. Эта функция загружает предыдущее состояние ViewState, из которого мы узнаем состояние обновления. Ключевой частью является проверка значения _refreshstate и сверка на идентичность со значением, хранящимся в сессионной переменной, если они равны, значит, пользователь обновлял страницу.
     Функция SaveViewState сохраняет текущее значение _refreshState в сессии, так что позже мы можем проверить – обновлял ли пользователь страницу путём нажатия на кнопку «Обновить».

Вывод

В этой статье продемонстрирован упрощённый метод определения события обновления страницы.

Вот и всё.


{К содержанию}

Форумы .Net - вопросы оставшиеся без ответа

Тип Image в MS SQL и MS Word VBA
Не могу законектить oracle из MS.NET Web приложения. Помогите пжлст.
отображение пустой даты
REFERER header
помогите потестировать
Как заставить ASPxDropDownList работать как DropDownList?
Dinamiceskaja Image v Header Crystal Reporta
CDO.Messge ... тонкость
ABBY Lingvo Automation
Контрол через appdomain


На этом сороковый выпуск .Net Собеседника закончен.
До следующего номера.



Чужа Виталий Ф. aka hDrummer, MCAD, MCDBA, MCP
hdrummer@sql.ru - жду ваши предложения и замечания.



http://subscribe.ru/
http://subscribe.ru/feedback/
Подписан адрес:
Код этой рассылки: comp.soft.prog.dotnetgrains
Отписаться

В избранное