День триста пятьдесят четвёртый. #ЗаметкиНаПолях
ASP.NET MVC 5.
Представления. Начало
Большинство методов действия контроллера должны отображать динамическую информацию в формате HTML. После того, как контроллер выполнил соответствующую логику для запрошенного URL, он делегирует отображение результата представлению.
В отличие от файловых веб-платформ сами представления непосредственно недоступны. Нельзя задать в браузере путь к представлению и сделать так, чтобы оно отобразилось. Вместо этого представление всегда отображается контроллером, который передаёт представлению данные для отображения.
В ASP.NET представления — это файлы
Представления, как правило, возвращаются из методов действия в виде объекта
ViewBag и ViewData
Помимо модели, для передачи небольших объёмов данных в представление из метода действия используется специальный словарь
Строго типизированные представления
Если в представление нужно передать модель, то создаётся строго типизированное представление. Оно отличается от обычного указанием в заголовке файла представления типа модели через декларацию
Модели представления
Иногда в представлении нужно отобразить дополнительную информацию, помимо данных из модели домена. Например, в представлении корзины покупок помимо списка товаров нужно отобразить общую сумму покупки и сообщение (допустим, информацию о доставке).
Есть два пути добиться этого: использовать
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 3.
ASP.NET MVC 5.
Представления. Начало
Большинство методов действия контроллера должны отображать динамическую информацию в формате HTML. После того, как контроллер выполнил соответствующую логику для запрошенного URL, он делегирует отображение результата представлению.
В отличие от файловых веб-платформ сами представления непосредственно недоступны. Нельзя задать в браузере путь к представлению и сделать так, чтобы оно отобразилось. Вместо этого представление всегда отображается контроллером, который передаёт представлению данные для отображения.
В ASP.NET представления — это файлы
.cshtml
, в которых используется C# в разметке Razor. По соглашению представления размещаются в папке Views
, сгруппированы по папкам соответственно контроллеру, к которому они относятся, и называются по имени метода действия. Например, представления, относящиеся к контроллеру HomeController
, размещаются в папке Views/Home
. Представления для метода действия Index()
называется Index.cshtml
, для метода About()
– About.cshtml
. Общие представления, которые используются несколькими контроллерами, а также макеты страниц размещаются в папке Views/Shared
.Представления, как правило, возвращаются из методов действия в виде объекта
ViewResult
. Можно создавать и возвращать объект напрямую, однако обычно используется вспомогательный метод View
:public class HomeController : Controller {Соглашение об именовании помогает системе найти нужное представление в файле
public ActionResult About() {
return View();
}
}
Views/Home/About.cshtml
. Методу View
можно передать строковый параметр с указанием пути к нужному представлению, а также объект модели, данные которой нужно отобразить.ViewBag и ViewData
Помимо модели, для передачи небольших объёмов данных в представление из метода действия используется специальный словарь
ViewData
:ViewData["CurrentTime"] = DateTime.Now;С введением динамических типов в C#4 стало возможно использовать динамическую обёртку
ViewBag
, в котором можно задавать значения как свойства:ViewBag.CurrentTime = DateTime.Now;Этот код эквивалентен предыдущему, и технически ни один вариант не имеет преимущества перед другим. Однако в некоторых случаях
ViewData
может иметь преимущество, например, следующий код не выполнится из-за динамической природы ViewBag
: @Html.TextBox("name", ViewBag.Name)
Здесь нужно либо использовать ViewData["Name"]
, либо приводить значение к нужному типу: (string)ViewBag.Name
.Строго типизированные представления
Если в представление нужно передать модель, то создаётся строго типизированное представление. Оно отличается от обычного указанием в заголовке файла представления типа модели через декларацию
@model
. Следующая декларация объявляет строго типизированное представления для списка товаров:@model IEnumerable<Product>Это позволяет компилятору проверять типы данных модели, в отличие от передачи данных через
ViewBag
/ViewData
, а разработчикам использовать преимущества IntelliSense в представлении.Модели представления
Иногда в представлении нужно отобразить дополнительную информацию, помимо данных из модели домена. Например, в представлении корзины покупок помимо списка товаров нужно отобразить общую сумму покупки и сообщение (допустим, информацию о доставке).
Есть два пути добиться этого: использовать
ViewBag
/ViewData
, либо создать специализированный класс модели представления, содержащий как список продуктов, так и необходимые дополнительные свойства:public class ShoppingCartViewModel {Как правило, лучше использовать второй вариант. Можно рассматривать модель представления как модель, существующую только для передачи информации в представление.
public IEnumerable<Product> Products { get; set; }
public decimal CartTotal { get; set; }
public string Message { get; set; }
}
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 3.
День триста пятьдесят пятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
Представления. Razor
Механизм представления Razor является механизмом создания представлений по умолчанию. Он предоставляет оптимизированный синтаксис, который сводит к минимуму количество необходимого кода. Cовет по использованию Razor: помните, что он был разработан, чтобы быть простым и интуитивно понятным. Чаще всего вам не нужно беспокоиться о синтаксисе: просто пишите HTML и используйте знак
Выражения
В большинстве случаев не нужно использовать закрывающий тэг:
Razor достаточно умён, чтобы понимать стандартные форматы e-mail адресов:
Это части представления, которые выполняются компилятором. Их заключают в фигурные скобки:
Razor ищет начало HTML тэга для определения окончания кода и начала разметки, однако если нужно вывести текст сразу после блока кода, можно использовать либо специальный тег
Для комментариев на стороне сервера используется конструкция
Поскольку угловые скобки используются как для HTML тегов, так и в обобщённых методах, вызвать обобщённый метод можно, заключив выражение в круглые скобки:
По умолчанию весь код HTML, выводящийся через Razor кодируется для предотвращения XSS атак (
ASP.NET MVC 5.
Представления. Razor
Механизм представления Razor является механизмом создания представлений по умолчанию. Он предоставляет оптимизированный синтаксис, который сводит к минимуму количество необходимого кода. Cовет по использованию Razor: помните, что он был разработан, чтобы быть простым и интуитивно понятным. Чаще всего вам не нужно беспокоиться о синтаксисе: просто пишите HTML и используйте знак
@
, когда нужно вставить какой-то код.Выражения
В большинстве случаев не нужно использовать закрывающий тэг:
<p>Всего @items.Length элементов</p>Razor понимает, что точка, за которой следует набор букв, означает обращение к свойству объекта, а пробел или знак < не являются валидными символами. Однако, если нужно вывести переменную, а за ней точку и текст, можно использовать круглые скобки:
<p>Всего элементов @items.Length</p>
<p>Всего элементов @items.Length.</p>
<p>@(siteName).Com</p>
Также скобки можно использовать для вычисления выражений: <p>@(1+2)</p>
E-mailRazor достаточно умён, чтобы понимать стандартные форматы e-mail адресов:
<span>[email protected]</span>
В более сложных случаях, а также для указания аккаунтов Twitter или Telegram, можно использовать @@
: <p>@@NetDeveloperDiary</p>
Блоки кодаЭто части представления, которые выполняются компилятором. Их заключают в фигурные скобки:
@{Совмещение кода и разметки
int x = 123;
string y = "hello";
}
@foreach (var item in items) {Совмещение кода и текста
<span>@item.Name.</span>
}
Razor ищет начало HTML тэга для определения окончания кода и начала разметки, однако если нужно вывести текст сразу после блока кода, можно использовать либо специальный тег
<text>
, который не выводится на странице, либо конструкцию @:
(она позволяет вывести только одну строку):@if (showMessage) {или
<text>Это простой текст</text>
}
@if (showMessage) {Серверный комментарий
@:Это простой текст
}
Для комментариев на стороне сервера используется конструкция
@* *@
:@* Это многострочный комментарий.Вызов обобщённого метода
@if (showMessage) {
<h1>@ViewBag.Message</h1>
}
Всё это закомментировано.
*@
Поскольку угловые скобки используются как для HTML тегов, так и в обобщённых методах, вызвать обобщённый метод можно, заключив выражение в круглые скобки:
@(Html.SomeMethod<AType>())Кодирование HTML
По умолчанию весь код HTML, выводящийся через Razor кодируется для предотвращения XSS атак (
<
становится <
, >
- >
и т.п.). Поэтому, если вы действительно хотите вывести HTML код, как есть, используйте вспомогательный метод HTML.Raw
:<span>@Html.Raw(model.Message)</span>Внимание: Javascript не кодируется по умолчанию, как HTML. Поэтому любые данные, которые будут использоваться внутри кода Javascript, нужно кодировать с помощью
@Ajax.JavaScriptStringEncode
:<script type="text/javascript">Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 3.
$(“.title”).text('Hello @Ajax.JavaScriptStringEncode(ViewBag.Username)');
</script>
День триста пятьдесят шестой. #DesignPatterns
Паттерны проектирования
9. Паттерн «Цепочка обязанностей» (Chain of Responsibility).
Как и многие другие поведенческие паттерны, Цепочка обязанностей базируется на том, чтобы превратить отдельные поведения в объекты-обработчики. Кроме того, паттерн подразумевает связывание объектов-обработчиков в одну цепь.
Назначение: позволяет избежать привязки отправителя запроса к его получателю, давая шанс обработать запрос нескольким объектам. Связывает объекты-получатели в цепочку и передает запрос вдоль этой цепочки, пока его не обработают. Отправитель запроса знает только о первом обработчике, но не знает, кто в итоге обработает запрос.
Причины использования:
Необходимость обработки пользовательского запроса несколькими независимыми друг от друга методами: аутентификация и авторизация, валидация данных, предотвращение массовых запросов ботами, собственно выполнение запроса и т.п. Каждая новая проверка раздувает код обработки, а для обработки схожих запросов код приходится дублировать.
Решением будет вынести каждую проверку в отдельный класс обработчика, реализующий общий интерфейс, и выстроить эти классы в цепочку обработки.
Классическая диаграмма приведена на рисунке ниже:
-
-
-
Логику обработки можно реализовать по-разному. В примере выше каждый обработчик передавал бы запрос следующему по цепочке только в случае успешной обработки. Например, только в случае успешной авторизации пользователя мы проверяем валидность данных его запроса. В противном случае обработка запроса прекращается.
Но есть и другой подход, при котором обработчики прерывают цепь только когда они могут обработать запрос. В этом случае запрос движется по цепи, пока не найдётся обработчик, который может его обработать. Очень часто такой подход используется для передачи событий, создаваемых классами графического интерфейса в результате взаимодействия с пользователем.
Например, когда пользователь кликает по кнопке, программа выстраивает цепочку из объекта этой кнопки, всех её родительских элементов и общего окна приложения на конце. Событие клика передаётся по этой цепи до тех пор, пока не найдётся объект, способный его обработать.
Важно, чтобы все объекты цепочки имели общий интерфейс. Обычно каждому конкретному обработчику достаточно знать только то, что следующий объект в цепи имеет метод
Источники:
- Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 7.
- https://refactoring.guru/ru/design-patterns/chain-of-responsibility
Паттерны проектирования
9. Паттерн «Цепочка обязанностей» (Chain of Responsibility).
Как и многие другие поведенческие паттерны, Цепочка обязанностей базируется на том, чтобы превратить отдельные поведения в объекты-обработчики. Кроме того, паттерн подразумевает связывание объектов-обработчиков в одну цепь.
Назначение: позволяет избежать привязки отправителя запроса к его получателю, давая шанс обработать запрос нескольким объектам. Связывает объекты-получатели в цепочку и передает запрос вдоль этой цепочки, пока его не обработают. Отправитель запроса знает только о первом обработчике, но не знает, кто в итоге обработает запрос.
Причины использования:
Необходимость обработки пользовательского запроса несколькими независимыми друг от друга методами: аутентификация и авторизация, валидация данных, предотвращение массовых запросов ботами, собственно выполнение запроса и т.п. Каждая новая проверка раздувает код обработки, а для обработки схожих запросов код приходится дублировать.
Решением будет вынести каждую проверку в отдельный класс обработчика, реализующий общий интерфейс, и выстроить эти классы в цепочку обработки.
Классическая диаграмма приведена на рисунке ниже:
-
Client
- отправляет запрос объекту Handler
.-
Handler
- определяет интерфейс для обработки запроса. Также может определять ссылку на следующий обработчик запроса.-
ConcreteHandler1
и ConcreteHandler2
- конкретные обработчики, которые реализуют функционал обработки запроса.Логику обработки можно реализовать по-разному. В примере выше каждый обработчик передавал бы запрос следующему по цепочке только в случае успешной обработки. Например, только в случае успешной авторизации пользователя мы проверяем валидность данных его запроса. В противном случае обработка запроса прекращается.
Но есть и другой подход, при котором обработчики прерывают цепь только когда они могут обработать запрос. В этом случае запрос движется по цепи, пока не найдётся обработчик, который может его обработать. Очень часто такой подход используется для передачи событий, создаваемых классами графического интерфейса в результате взаимодействия с пользователем.
Например, когда пользователь кликает по кнопке, программа выстраивает цепочку из объекта этой кнопки, всех её родительских элементов и общего окна приложения на конце. Событие клика передаётся по этой цепи до тех пор, пока не найдётся объект, способный его обработать.
Важно, чтобы все объекты цепочки имели общий интерфейс. Обычно каждому конкретному обработчику достаточно знать только то, что следующий объект в цепи имеет метод
HandleRequest()
. Благодаря этому связи между объектами цепочки будут более гибкими. Кроме того, можно формировать цепочки на лету из разнообразных объектов, не привязываясь к конкретным классам.Источники:
- Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 7.
- https://refactoring.guru/ru/design-patterns/chain-of-responsibility
День триста пятьдесят седьмой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
20. Развёртывайте как Можно Раньше и Чаще
Отладка процесса развёртывания и установки приложения часто откладывается до конца проекта. В некоторых проектах написание инструментария установки делегируется инженеру по выпуску, который воспринимает задачу как «необходимое зло». Обзоры и демонстрации выполняются в среде, созданной вручную, чтобы убедиться, что всё работает. В результате разработчики не получают никакого опыта развёртывания или поведения приложения в реальных условиях, пока не станет слишком поздно вносить изменения.
Процесс установки/развертывания — это первое, что видит клиент, и чем он проще, тем надёжнее (или, по крайней мере, проще в отладке) производственная среда. Развёрнутое программное обеспечение — это то, что клиент будет использовать. Не обеспечив правильную настройку приложения при развёртывании, вы посеете сомнения в работе вашего приложения у клиентов ещё до того, как они начнут его использовать.
Начиная разработку вашего проекта с процесса установки, вы получите необходимое время для его эволюции по ходу разработки, а также возможность внести изменения в код приложения, чтобы упростить установку. Периодический запуск и тестирование процесса установки в чистой среде также обеспечивает гарантию того, что вы не сделали предположений в коде, основанных на среде разработки или тестирования.
Позднее развёртывание означает, что процесс развёртывания может быть более сложным, чтобы обойти предположения в коде. То, что казалось отличной идеей в IDE, где у вас есть полный контроль над средой, может сделать процесс развёртывания намного более сложным. Лучше знать об возможных проблемах раньше, чем позже.
Хотя «лёгкость развёртывания» вряд ли несёт большую коммерческую ценность на раннем этапе по сравнению с демонстрацией приложения на ноутбуке разработчика, простая истина заключается в том, что пока вы не сможете продемонстрировать своё приложение в целевой среде, вам за него не заплатят. Если ваше обоснование для откладывания процесса развертывания состоит в том, что процесс тривиален, всё равно сделайте это, поскольку стоимость этого будет низка. Если же процесс слишком сложен или имеет слишком неопределён, делайте с процессом развёртывания то же, что вы делаете с кодом приложения: экспериментируйте, оценивайте и изменяйте процесс развёртывания по мере необходимости.
Процесс установки/развёртывания важен для продуктивности ваших клиентов или вашей службы поддержки, поэтому вы должны тестировать и изменять этот процесс по мере необходимости. Мы тестируем и изменяем исходный код на протяжении всего проекта. Развёртывание заслуживает не меньшего внимания.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Steve Berczuk
97 Вещей, Которые Должен Знать Каждый Программист
20. Развёртывайте как Можно Раньше и Чаще
Отладка процесса развёртывания и установки приложения часто откладывается до конца проекта. В некоторых проектах написание инструментария установки делегируется инженеру по выпуску, который воспринимает задачу как «необходимое зло». Обзоры и демонстрации выполняются в среде, созданной вручную, чтобы убедиться, что всё работает. В результате разработчики не получают никакого опыта развёртывания или поведения приложения в реальных условиях, пока не станет слишком поздно вносить изменения.
Процесс установки/развертывания — это первое, что видит клиент, и чем он проще, тем надёжнее (или, по крайней мере, проще в отладке) производственная среда. Развёрнутое программное обеспечение — это то, что клиент будет использовать. Не обеспечив правильную настройку приложения при развёртывании, вы посеете сомнения в работе вашего приложения у клиентов ещё до того, как они начнут его использовать.
Начиная разработку вашего проекта с процесса установки, вы получите необходимое время для его эволюции по ходу разработки, а также возможность внести изменения в код приложения, чтобы упростить установку. Периодический запуск и тестирование процесса установки в чистой среде также обеспечивает гарантию того, что вы не сделали предположений в коде, основанных на среде разработки или тестирования.
Позднее развёртывание означает, что процесс развёртывания может быть более сложным, чтобы обойти предположения в коде. То, что казалось отличной идеей в IDE, где у вас есть полный контроль над средой, может сделать процесс развёртывания намного более сложным. Лучше знать об возможных проблемах раньше, чем позже.
Хотя «лёгкость развёртывания» вряд ли несёт большую коммерческую ценность на раннем этапе по сравнению с демонстрацией приложения на ноутбуке разработчика, простая истина заключается в том, что пока вы не сможете продемонстрировать своё приложение в целевой среде, вам за него не заплатят. Если ваше обоснование для откладывания процесса развертывания состоит в том, что процесс тривиален, всё равно сделайте это, поскольку стоимость этого будет низка. Если же процесс слишком сложен или имеет слишком неопределён, делайте с процессом развёртывания то же, что вы делаете с кодом приложения: экспериментируйте, оценивайте и изменяйте процесс развёртывания по мере необходимости.
Процесс установки/развёртывания важен для продуктивности ваших клиентов или вашей службы поддержки, поэтому вы должны тестировать и изменять этот процесс по мере необходимости. Мы тестируем и изменяем исходный код на протяжении всего проекта. Развёртывание заслуживает не меньшего внимания.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Steve Berczuk
День триста пятьдесят девятый. #NetInternals
Начинаю новую серию постов в стиле вопросы и ответы из книги Адама Фурманека «.NET Internals Cookbook».
От автора: "В этой серии я отвечаю на различные вопросы по .NET. Некоторые из них задают на собеседованиях, некоторые я вижу в Интернете, остальные придуманы. Цель - предоставить краткий ответ со ссылками на источники, если это необходимо. Это ни в коем случае не учебник по .NET, это просто набор полезных ответов, чтобы освежить ваши знания."
1. Что происходит, когда вы выбрасываете что-то, что не наследуется от System.Exception? Изменилось ли это со времён .NET 1?
Во-первых, у вас может возникнуть вопрос: «Как вообще это сделать?» Помимо C# существуют другие языки, работающие в CLR. Одним из них является C++/CLI, который является управляемой версией языка C++. В C++ вы можете выбрасывать что угодно –
Выбрасываемый объект помещается в System.Runtime.CompilerServices.RuntimeWrappedException, поэтому вы всё равно сможете перехватить исключение с помощью обычного блока
Однако до .NET 2 всё было иначе. Выброшенный объект оборачивался, поэтому вы не могли поймать его таким образом. Вам пришлось бы использовать нетипизированную версию блока catch в виде
Источник: Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
Начинаю новую серию постов в стиле вопросы и ответы из книги Адама Фурманека «.NET Internals Cookbook».
От автора: "В этой серии я отвечаю на различные вопросы по .NET. Некоторые из них задают на собеседованиях, некоторые я вижу в Интернете, остальные придуманы. Цель - предоставить краткий ответ со ссылками на источники, если это необходимо. Это ни в коем случае не учебник по .NET, это просто набор полезных ответов, чтобы освежить ваши знания."
1. Что происходит, когда вы выбрасываете что-то, что не наследуется от System.Exception? Изменилось ли это со времён .NET 1?
Во-первых, у вас может возникнуть вопрос: «Как вообще это сделать?» Помимо C# существуют другие языки, работающие в CLR. Одним из них является C++/CLI, который является управляемой версией языка C++. В C++ вы можете выбрасывать что угодно –
integer
, string
, byte
и т.д. Если вы попытаетесь сделать это в C++/CLI, вы фактически выбросите нечто, что не наследует от System.Exception
.Выбрасываемый объект помещается в System.Runtime.CompilerServices.RuntimeWrappedException, поэтому вы всё равно сможете перехватить исключение с помощью обычного блока
catch (Exception e) {}
.Однако до .NET 2 всё было иначе. Выброшенный объект оборачивался, поэтому вы не могли поймать его таким образом. Вам пришлось бы использовать нетипизированную версию блока catch в виде
catch {}
. По этой причине вы могли видеть код, подобный следующему:tryПосле перехода на .NET 2 этот код перестанет компилироваться, потому что последний блок
{
//
}
catch(Exception e)
{
//
}
catch
{
//
}
catch
никогда не будет выполняться. Вы можете изменить код или восстановить старое поведение, используя атрибут RuntimeCompatibilityAttribute.Источник: Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
День триста шестидесятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
Модели
Слово модель в разработке ПО означает сотни различных концепций. Даже применительно к MVC можно говорить о моделях бизнес-логики (домена) и модели представления. Далее под моделью понимаются объекты, которые используются для отправки информации в базу данных, выполнения бизнес-логики и даже визуализации в представлении. Другими словами, эти объекты представляют домен, на котором построено приложение, а модели — это объекты, которые вы хотите отображать, сохранять, создавать, обновлять и удалять.
ASP.NET MVC 5 предоставляет ряд инструментов и функций для построения функционала приложения, используя только определение объектов модели. Например, для корзины покупок можно написать простые классы C#
Скаффолдинг
Автоматизированные работы по созданию контроллеров и представлений называются скаффолдингом. Скаффолдинг в ASP.NET MVC может сгенерировать шаблонный код, необходимый для функционала создания, чтения, обновления и удаления (CRUD) данных в приложении. Шаблоны скаффолдинга могут проверять определение типа для модели и генерировать контроллер, связанные с ним представления, а в некоторых случаях и классы доступа к данным. Скаффолдинг знает, как назвать контроллеры и представления, какой код должен идти в каждом компоненте и где разместить все эти части в проекте, чтобы приложение работало.
Не ожидайте, что скаффолдинг создаст за вас всё приложение, но он освободит вас от скучной работы по написанию 100% кода приложения вручную. Вы можете настроить и отредактировать результаты скаффолдинга, чтобы настроить приложение под себя.
Entity Framework
EF - это фреймворк объектно-реляционного отображения (object-relational mapping - ORM), которая понимает, как хранить объекты .NET в реляционной базе данных и извлекать их, используя LINQ.
EF поддерживает несколько стилей разработки: database-first («сначала база данных»), model-first («сначала модель») и code-first («сначала код»). Скаффолдинг в ASP.NET MVC использует стиль code-first. Это означает, что вы можете приступить к хранению и извлечению информации из БД, не создавая самой БД. Вместо этого вы пишете классы C#, а EF выясняет, как и где хранить экземпляры этих классов.
Привязка модели
Привязка модели — это процесс создания объектов модели, используя данные, отправленные браузером в HTTP-запросе. Вместо того, чтобы перебирать все значения, отправленные на сервер формой, мы полагаемся на соглашение об именовании и используем привязку модели, которая сделает это за нас. Привязка модели использует компоненты, которые называются провайдерами значений для поиска нужных значений в различных параметрах запроса: маршруте, строке запроса или данных формы. Это позволяет использовать, например, следующий метод действия для запроса HTTP GET:
Для запросов HTTP POST можно использовать целый объект модели:
Привязку модели можно вызывать вручную внутри метода действия с помощью методов
ASP.NET MVC 5.
Модели
Слово модель в разработке ПО означает сотни различных концепций. Даже применительно к MVC можно говорить о моделях бизнес-логики (домена) и модели представления. Далее под моделью понимаются объекты, которые используются для отправки информации в базу данных, выполнения бизнес-логики и даже визуализации в представлении. Другими словами, эти объекты представляют домен, на котором построено приложение, а модели — это объекты, которые вы хотите отображать, сохранять, создавать, обновлять и удалять.
ASP.NET MVC 5 предоставляет ряд инструментов и функций для построения функционала приложения, используя только определение объектов модели. Например, для корзины покупок можно написать простые классы C#
Product
, ShoppingCart
и User
для представления основных объектов. После этого можно использовать инструменты MVC, для создания контроллеров и представлений для стандартных сценариев отображения, создания, редактирования и удаления для каждого из объектов модели.Скаффолдинг
Автоматизированные работы по созданию контроллеров и представлений называются скаффолдингом. Скаффолдинг в ASP.NET MVC может сгенерировать шаблонный код, необходимый для функционала создания, чтения, обновления и удаления (CRUD) данных в приложении. Шаблоны скаффолдинга могут проверять определение типа для модели и генерировать контроллер, связанные с ним представления, а в некоторых случаях и классы доступа к данным. Скаффолдинг знает, как назвать контроллеры и представления, какой код должен идти в каждом компоненте и где разместить все эти части в проекте, чтобы приложение работало.
Не ожидайте, что скаффолдинг создаст за вас всё приложение, но он освободит вас от скучной работы по написанию 100% кода приложения вручную. Вы можете настроить и отредактировать результаты скаффолдинга, чтобы настроить приложение под себя.
Entity Framework
EF - это фреймворк объектно-реляционного отображения (object-relational mapping - ORM), которая понимает, как хранить объекты .NET в реляционной базе данных и извлекать их, используя LINQ.
EF поддерживает несколько стилей разработки: database-first («сначала база данных»), model-first («сначала модель») и code-first («сначала код»). Скаффолдинг в ASP.NET MVC использует стиль code-first. Это означает, что вы можете приступить к хранению и извлечению информации из БД, не создавая самой БД. Вместо этого вы пишете классы C#, а EF выясняет, как и где хранить экземпляры этих классов.
Привязка модели
Привязка модели — это процесс создания объектов модели, используя данные, отправленные браузером в HTTP-запросе. Вместо того, чтобы перебирать все значения, отправленные на сервер формой, мы полагаемся на соглашение об именовании и используем привязку модели, которая сделает это за нас. Привязка модели использует компоненты, которые называются провайдерами значений для поиска нужных значений в различных параметрах запроса: маршруте, строке запроса или данных формы. Это позволяет использовать, например, следующий метод действия для запроса HTTP GET:
public ActionResult Edit (int id) { … }Здесь привязка модели будет искать параметр
id
в маршруте, например, /Store/Edit/5
, либо в строке запроса /Store/Edit/?id=5
.Для запросов HTTP POST можно использовать целый объект модели:
[HttpPost]Тогда связыватель модели для каждого свойства класса Product будет искать параметр с соответствующим именем в параметрах запроса.
public ActionResult Edit (Product product) { … }
Привязку модели можно вызывать вручную внутри метода действия с помощью методов
UpdateModel
или TryUpdateModel
. Кроме того, проверить успешность связывания можно с помощью статического свойства IsValid
класса ModelState
:[HttpPost]Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 4.
public ActionResult Edit() {
var album = new Album();
TryUpdateModel(album);
if (ModelState.IsValid) {
// Успех. Обрабатываем модель
}
else {
// Неудача. Сообщаем пользователю об ошибке
}
}
День триста шестьдесят первый. #DesignPatterns
Паттерны проектирования
10. Паттерн «Одиночка» (Singleton). Начало
По определению паттерн «Одиночка» гарантирует, что у некоего класса есть лишь один экземпляр. В некоторых случаях анализ предметной области строго требует, чтобы класс существовал лишь в одном экземпляре. Однако на практике «Синглтон» обычно используется для обеспечения доступа к какому-либо ресурсу, который требуется разным частям приложения.
Назначение: гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему. Другими словами, синглтон эмулирует глобальные переменные в объектно-ориентированных языках программирования.
Причины использования:
Практически в любом приложении возникает необходимость в глобальных переменных или объектах с ограниченным числом экземпляров. И самый простой способ решить эту задачу — создать глобальный объект, который будет доступен из любой точки приложения.
Классическая диаграмма приведена на рисунке ниже.
В оригинальном описании паттерна «Синглтон» «бандой четырех» на его реализацию не накладывались никакие ограничения, однако на практике любая реализация должна отвечать двум требованиям:
- в многопоточной среде должна обеспечиваться возможность доступа к синглтону;
- должна обеспечиваться «ленивость» создания синглтона.
Реализация на основе Lazy<T> (.Net 4.0+):
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 8.
Паттерны проектирования
10. Паттерн «Одиночка» (Singleton). Начало
По определению паттерн «Одиночка» гарантирует, что у некоего класса есть лишь один экземпляр. В некоторых случаях анализ предметной области строго требует, чтобы класс существовал лишь в одном экземпляре. Однако на практике «Синглтон» обычно используется для обеспечения доступа к какому-либо ресурсу, который требуется разным частям приложения.
Назначение: гарантирует, что у класса есть только один экземпляр, и предоставляет глобальную точку доступа к нему. Другими словами, синглтон эмулирует глобальные переменные в объектно-ориентированных языках программирования.
Причины использования:
Практически в любом приложении возникает необходимость в глобальных переменных или объектах с ограниченным числом экземпляров. И самый простой способ решить эту задачу — создать глобальный объект, который будет доступен из любой точки приложения.
Классическая диаграмма приведена на рисунке ниже.
В оригинальном описании паттерна «Синглтон» «бандой четырех» на его реализацию не накладывались никакие ограничения, однако на практике любая реализация должна отвечать двум требованиям:
- в многопоточной среде должна обеспечиваться возможность доступа к синглтону;
- должна обеспечиваться «ленивость» создания синглтона.
Реализация на основе Lazy<T> (.Net 4.0+):
public sealed class LazySingletonГлавными недостатками синглтонов считаются невозможность юнит-тестирования классов, которые пользуются услугами синглтона, и низкая гибкость. Но при небольшой модификации это можно исправить. Основная суть такой модификации состоит в том, что статическое свойство
{
private static readonly Lazy<LazySingleton>
_instance =
new Lazy<LazySingleton>(
() => new LazySingleton());
LazySingleton() { }
public static LazySingleton Instance {
get { return _instance.Value; }
}
}
Instance
вместо возврата конкретного класса возвращает экземпляр абстрактного класса или интерфейса. Также появляется мутатор (set
) свойства, который позволяет установить нужный экземпляр синглтона при старте приложения, во время смены контекста или во время инициализации юнит-тестов. В результате решение будет более гибким и тестируемым.Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 8.
День триста шестьдесят второй. #DesignPatterns
Паттерны проектирования
10. Паттерн «Одиночка» (Singleton). Окончание
«Синглтон» — это самый критикуемый паттерн, описанный «бандой четырех», главный недостаток которого кроется в его определении: синглтон гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Проблема № 1: «Синглтон гарантирует, что у класса есть только один экземпляр…»
На самом деле бизнес-логика очень редко накладывает жесткие ограничения на количество экземпляров класса. Обычно это наши с вами уловки и попытки оправдать ошибки дизайна: легче связать несколько кусков системы с помощью синглтонов, вместо того чтобы изменить дизайн и передать классам лишь нужные зависимости.
Проблема № 2: «… и предоставляет глобальную точку доступа»
Главная проблема паттерна «Синглтон» заключается в том, что он является глобальной переменной со всеми её недостатками.
- Необходимость конструктора по умолчанию (для ленивой реализации). Это значит, что синглтону нельзя передать требуемые зависимости и он будет использовать другие глобальные объекты. В результате легко прийти к дизайну приложения, состоящего из набора глобальных объектов.
- Неявные зависимости. Если класс имеет много открытых полей или его конструктор принимает слишком большое число аргументов, то он считается сложным, и с его дизайном что-то не так. Но что, если класс не содержит полей и не принимает никаких зависимостей через конструктор, но использует несколько синглтонов? Тогда, чтобы понять его сложность, придется проанализировать все закрытые методы.
- Изменяемое состояние. Это является источником очень коварных ошибок. Внесение изменений в одну часть системы может изменить работу произвольного числа модулей, у которых были определенные предположения относительно состояния синглтона. Синглтон может обладать невидимым состоянием, например кэшированием, но полноценной изменяемости нужно избегать всеми силами.
Возможное применение
1. Синглтон без видимого состояния. Используется, чтобы получить доступ к стабильной справочной информации или некоторым утилитам.
2. Настраиваемый контекст. Синглтон возвращает абстрактный класс или интерфейс, который можно установить при старте приложения или при инициализации юнит-теста.
Советы по использованию
1. Минимальная область использования. Ограничьте использование синглтона минимальным числом классов/модулей. Чем меньше у него прямых пользователей, тем легче будет от него избавиться и перейти на более продуманную модель управления зависимостями. Чем больше у класса пользователей, тем сложнее его изменить. Если вы вынуждены использовать синглтон, то пусть лишь несколько высокоуровневых классов-медиаторов используют его напрямую и передают его экземпляр в качестве зависимостей классам более низкого уровня.
2. Сделайте использование синглтона явным. Если передать зависимость через аргументы конструктора не удается, то сделайте использование синглтона явным. Вместо обращения к синглтону из нескольких методов сделайте статическую переменную и проинициализируйте её экземпляром синглтона.
3. Синглтон или статический класс. Альтернативой паттерну «Синглтон» является использование класса с исключительно статическими членами. Синглтон явно обладает большей гибкостью, но статическими функциями проще пользоваться. Можно предложить следующее правило: при отсутствии состояния и небольшом числе операций используйте статические методы. Если же глобальный объект обладает состоянием, то синглтон будет проще.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 8.
Паттерны проектирования
10. Паттерн «Одиночка» (Singleton). Окончание
«Синглтон» — это самый критикуемый паттерн, описанный «бандой четырех», главный недостаток которого кроется в его определении: синглтон гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Проблема № 1: «Синглтон гарантирует, что у класса есть только один экземпляр…»
На самом деле бизнес-логика очень редко накладывает жесткие ограничения на количество экземпляров класса. Обычно это наши с вами уловки и попытки оправдать ошибки дизайна: легче связать несколько кусков системы с помощью синглтонов, вместо того чтобы изменить дизайн и передать классам лишь нужные зависимости.
Проблема № 2: «… и предоставляет глобальную точку доступа»
Главная проблема паттерна «Синглтон» заключается в том, что он является глобальной переменной со всеми её недостатками.
- Необходимость конструктора по умолчанию (для ленивой реализации). Это значит, что синглтону нельзя передать требуемые зависимости и он будет использовать другие глобальные объекты. В результате легко прийти к дизайну приложения, состоящего из набора глобальных объектов.
- Неявные зависимости. Если класс имеет много открытых полей или его конструктор принимает слишком большое число аргументов, то он считается сложным, и с его дизайном что-то не так. Но что, если класс не содержит полей и не принимает никаких зависимостей через конструктор, но использует несколько синглтонов? Тогда, чтобы понять его сложность, придется проанализировать все закрытые методы.
- Изменяемое состояние. Это является источником очень коварных ошибок. Внесение изменений в одну часть системы может изменить работу произвольного числа модулей, у которых были определенные предположения относительно состояния синглтона. Синглтон может обладать невидимым состоянием, например кэшированием, но полноценной изменяемости нужно избегать всеми силами.
Возможное применение
1. Синглтон без видимого состояния. Используется, чтобы получить доступ к стабильной справочной информации или некоторым утилитам.
2. Настраиваемый контекст. Синглтон возвращает абстрактный класс или интерфейс, который можно установить при старте приложения или при инициализации юнит-теста.
Советы по использованию
1. Минимальная область использования. Ограничьте использование синглтона минимальным числом классов/модулей. Чем меньше у него прямых пользователей, тем легче будет от него избавиться и перейти на более продуманную модель управления зависимостями. Чем больше у класса пользователей, тем сложнее его изменить. Если вы вынуждены использовать синглтон, то пусть лишь несколько высокоуровневых классов-медиаторов используют его напрямую и передают его экземпляр в качестве зависимостей классам более низкого уровня.
2. Сделайте использование синглтона явным. Если передать зависимость через аргументы конструктора не удается, то сделайте использование синглтона явным. Вместо обращения к синглтону из нескольких методов сделайте статическую переменную и проинициализируйте её экземпляром синглтона.
3. Синглтон или статический класс. Альтернативой паттерну «Синглтон» является использование класса с исключительно статическими членами. Синглтон явно обладает большей гибкостью, но статическими функциями проще пользоваться. Можно предложить следующее правило: при отсутствии состояния и небольшом числе операций используйте статические методы. Если же глобальный объект обладает состоянием, то синглтон будет проще.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 8.
День триста шестьдесят третий. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
21. Разделяйте Исключения Бизнес-логики от Технических
По сути, есть всего две причины, из-за которых что-то может пойти не так во время выполнения программы. Это технические проблемы, мешающие работе приложения, и бизнес-логика, не дающая нам использовать приложение неправильно. Большинство современных языков, таких как LISP, Java, Smalltalk и C#, используются исключения для сообщения о возникновении обеих ситуаций. Тем не менее, эти ситуации настолько различны, что относиться к ним следует по-разному. Использование для них одной иерархии исключений, не говоря уже об одних и тех же классах исключений, - это потенциальный источник путаницы.
При возникновении программной ошибки может возникнуть неразрешимая техническая проблема. Например, попытка получить доступ к элементу 83 из массива размера 17, не позволяет программе продолжить выполняться корректно и должна приводить к какому-то исключению. Чуть менее очевидный пример: вызов некоторой библиотечной функции с неподходящими аргументами, приводящий к вышеописанной ситуации внутри библиотеки.
Было бы ошибкой пытаться как-то разрешить те ситуации, которые вы сами вызвали. Вместо этого мы позволяем исключению всплыть на верхний уровень архитектуры и позволяем общему механизму обработки исключений сделать всё возможное, чтобы гарантировать, что система находится в безопасном состоянии: откатить транзакцию, сделать запись в журнале, а также создать дружелюбное сообщение для пользователя.
Вариант этой ситуации, когда вы разрабатываете библиотеку и вызывающая сторона нарушила контракт вашего метода, например, передала недопустимый аргумент или неправильно настроила зависимый объект. Это сравнимо с доступом к 83-му элементу из 17: вызывающий код должен отвечать за проверку, и отсутствие проверки - это ошибка программиста пользователя библиотеки. Правильная реакция на это - выбросить техническое исключение.
Другая, но всё же техническая, ситуация: программа не может продолжить работу из-за проблемы в среде выполнения, такой как не отвечающая база данных. В этой ситуации вы должны предположить, что инфраструктура сделала все возможное, чтобы решить проблему (например, повторила попытку восстановить соединение разумное количество раз) и потерпела неудачу. Даже если причина в другом, ситуация для вызывающего кода аналогична: мало что можно с этим поделать. В этом случае мы сообщаем об этом через исключение, которому позволяем всплыть до уровня общего механизма обработки исключений.
В противоположность этому ситуация, когда программа не может продолжить выполнение по причине ограничений домена. Такая ситуация является исключением, то есть необычна и нежелательна, но не является следствием программной ошибки. Например, попытка снять деньги со счёта с недостаточным количеством средств. Другими словами, такого рода ситуация является частью контракта приложения, и выброс исключения - это просто альтернативный путь обработки ситуации, являющейся частью предметной модели, о котором клиент должен знать и быть готовым к нему. Для этих ситуаций целесообразно создать отдельный вид исключения или отдельную иерархию исключений, чтобы клиент мог обрабатывать ситуацию особым образом.
Смешивание технических и бизнес-исключений в одной и той же иерархии стирает различие и сбивает вызывающего с толку в отношении того, что такое контракт метода, какие условия необходимо обеспечить перед вызовом и какие ситуации должны обрабатываться. Разделение этих случаев вносит ясность и увеличивает вероятность того, что технические исключения будут обрабатываться некоторой прикладной средой, в то время как исключения бизнес-сферы фактически рассматриваются и обрабатываются клиентским кодом.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Dan Bergh Johnson
97 Вещей, Которые Должен Знать Каждый Программист
21. Разделяйте Исключения Бизнес-логики от Технических
По сути, есть всего две причины, из-за которых что-то может пойти не так во время выполнения программы. Это технические проблемы, мешающие работе приложения, и бизнес-логика, не дающая нам использовать приложение неправильно. Большинство современных языков, таких как LISP, Java, Smalltalk и C#, используются исключения для сообщения о возникновении обеих ситуаций. Тем не менее, эти ситуации настолько различны, что относиться к ним следует по-разному. Использование для них одной иерархии исключений, не говоря уже об одних и тех же классах исключений, - это потенциальный источник путаницы.
При возникновении программной ошибки может возникнуть неразрешимая техническая проблема. Например, попытка получить доступ к элементу 83 из массива размера 17, не позволяет программе продолжить выполняться корректно и должна приводить к какому-то исключению. Чуть менее очевидный пример: вызов некоторой библиотечной функции с неподходящими аргументами, приводящий к вышеописанной ситуации внутри библиотеки.
Было бы ошибкой пытаться как-то разрешить те ситуации, которые вы сами вызвали. Вместо этого мы позволяем исключению всплыть на верхний уровень архитектуры и позволяем общему механизму обработки исключений сделать всё возможное, чтобы гарантировать, что система находится в безопасном состоянии: откатить транзакцию, сделать запись в журнале, а также создать дружелюбное сообщение для пользователя.
Вариант этой ситуации, когда вы разрабатываете библиотеку и вызывающая сторона нарушила контракт вашего метода, например, передала недопустимый аргумент или неправильно настроила зависимый объект. Это сравнимо с доступом к 83-му элементу из 17: вызывающий код должен отвечать за проверку, и отсутствие проверки - это ошибка программиста пользователя библиотеки. Правильная реакция на это - выбросить техническое исключение.
Другая, но всё же техническая, ситуация: программа не может продолжить работу из-за проблемы в среде выполнения, такой как не отвечающая база данных. В этой ситуации вы должны предположить, что инфраструктура сделала все возможное, чтобы решить проблему (например, повторила попытку восстановить соединение разумное количество раз) и потерпела неудачу. Даже если причина в другом, ситуация для вызывающего кода аналогична: мало что можно с этим поделать. В этом случае мы сообщаем об этом через исключение, которому позволяем всплыть до уровня общего механизма обработки исключений.
В противоположность этому ситуация, когда программа не может продолжить выполнение по причине ограничений домена. Такая ситуация является исключением, то есть необычна и нежелательна, но не является следствием программной ошибки. Например, попытка снять деньги со счёта с недостаточным количеством средств. Другими словами, такого рода ситуация является частью контракта приложения, и выброс исключения - это просто альтернативный путь обработки ситуации, являющейся частью предметной модели, о котором клиент должен знать и быть готовым к нему. Для этих ситуаций целесообразно создать отдельный вид исключения или отдельную иерархию исключений, чтобы клиент мог обрабатывать ситуацию особым образом.
Смешивание технических и бизнес-исключений в одной и той же иерархии стирает различие и сбивает вызывающего с толку в отношении того, что такое контракт метода, какие условия необходимо обеспечить перед вызовом и какие ситуации должны обрабатываться. Разделение этих случаев вносит ясность и увеличивает вероятность того, что технические исключения будут обрабатываться некоторой прикладной средой, в то время как исключения бизнес-сферы фактически рассматриваются и обрабатываются клиентским кодом.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Dan Bergh Johnson
День триста шестьдесят четвёртый. #юмор
В опенспейсах лично мне не доводилось работать. Зато дома при наличии детей - это да, очень похоже.
В опенспейсах лично мне не доводилось работать. Зато дома при наличии детей - это да, очень похоже.
День триста шестьдесят пятый. #NetInternals
2. Как проглотить ThreadAbortException?
Иногда в коде нужно остановить выполнение одного из потоков. Для этого можно использовать метод
Вы можете легко поймать его с помощью блока исключений, но, если вы не сбросите его, оно будет автоматически проброшено выше по стеку.
Еще одна особенность
Также вызов метода
В .NET Core метод
Источники:
- Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
- Евгений Пешков «Особые исключения в .NET» - https://youtu.be/WLSrYgMWif4
2. Как проглотить ThreadAbortException?
Иногда в коде нужно остановить выполнение одного из потоков. Для этого можно использовать метод
thread.Abort()
. При вызове метода Abort
в останавливаемом потоке выбрасывается исключение ThreadAbortException
.Вы можете легко поймать его с помощью блока исключений, но, если вы не сбросите его, оно будет автоматически проброшено выше по стеку.
var thread = new Thread(() => {Если всё-таки нужно обработать
try { … }
catch (ThreadAbortException e) {
…
}
});
…
thread.Abort();
ThreadAbort
и выполнить еще какие-то действия в останавливаемом потоке, то можно использовать метод Thread.ResetAbort()
. Он прекращает процесс остановки потока и исключение перестаёт прокидываться выше по стеку. Важно понимать, что метод thread.Abort()
сам по себе ничего не гарантирует — код в останавливаемом потоке может препятствовать остановке.Еще одна особенность
thread.Abort()
заключается в том, что он не сможет прервать код в том случае, если он находится в блоках catch
и finally
. Внутри кода фреймворка часто можно встретить методы, у которых блок try
пустой, а вся логика находится внутри finally
. Это делается как раз с той целью, чтобы этот код не мог быть прерван через ThreadAbortException
.Также вызов метода
thread.Abort()
дожидается выброса ThreadAbortException
. Объединим эти два факта и получим, что метод thread.Abort()
может заблокировать вызывающий поток:var thread = new Thread(() =>В реальности с этим можно столкнуться при использовании конструкции
{
try { }
catch {
//ThreadAbortException не выбрасывается в catch
}
finally {
//ThreadAbortException не выбрасывается в finally
Thread.Sleep(-1);
}
});
thread.Start();
…
thread.Abort(); //Никогда не вернётся
using
. Она разворачивается в try
/finally
, внутри finally
вызывается метод Dispose
. Он может быть сколь угодно сложным, содержать вызовы и обработчики событий, использовать блокировки. И если thread.Abort
был вызван во время выполнения Dispose
, то thread.Abort
будет его ждать. Так мы получаем блокировку почти на пустом месте.В .NET Core метод
thread.Abort()
выбрасывает PlatformNotSupportedException
. И это очень хорошо, потому что мотивирует пользоваться не thread.Abort()
, а неинвазивными методами остановки выполнения кода, например с помощью CancellationToken.Источники:
- Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
- Евгений Пешков «Особые исключения в .NET» - https://youtu.be/WLSrYgMWif4
День триста шестьдесят шестой. #Оффтоп #97Вещей
97 Вещей, Которые Должен Знать Каждый Программист
22. Занимайтесь Осознанной Практикой
Осознанная практика – это не просто выполнение работы. Если вы спросите себя «Почему я решаю эту задачу?» и ответом будет «Чтобы её решить», то вы не занимаетесь осознанной практикой.
Вы практикуетесь, чтобы улучшить ваш навык решать задачи. Речь идет о мастерстве и технике. Осознанная практика означает повторение. То есть выполнение задания с целью оттачивания мастерства в том или ином аспекте задания. Повторение уже повторенного. Методично, снова и снова, пока вы не достигнете желаемого уровня мастерства. Вы практикуетесь, чтобы отточить мастерство решения задачи, а не просто решить задачу.
Основная цель оплачиваемой разработки - завершить продукт, в то время как основная цель осознанной практики - повысить производительность. Это не одно и то же. Спросите себя, сколько времени вы тратите на разработку чужого продукта? А сколько на саморазвитие?
Сколько практики требуется, чтобы достичь мастерства? Peter Norvig пишет, что «около 10 000 часов… это магическое число». Mary Poppendieck в «Leading Lean Software Development» заметила, что «Хорошему исполнителю потребуется минимум 10 тысяч часов практики, чтобы стать экспертом».
Навык приходит постепенно, не сразу за 10 000 часов! Тем не менее, 10 000 часов это много: около 20 часов в неделю в течение 10 лет. Увидев эти цифры, можно подумать, что достичь уровня эксперта просто невозможно. Это не так. Уровень во многом зависит от осознанного выбора. Выбор за вами. Исследования последних двух десятилетий показали, что основным фактором приобретения опыта является время, затрачиваемое на осознанную практику. Врожденный талант не является основным фактором. По словам Mary Poppendieck: «Практически все исследователи уровня мастерства сходятся в том, что врожденный талант лишь начало. Необходимо иметь самый базовый уровень, чтобы начать. После чего успеха достигают те, кто больше других работает над этим.»
Нет смысла намеренно практиковать то, в чём вы уже являетесь экспертом. Осознанная практика означает практиковать то, в чем вы не очень хороши.
Peter Norvig: «Ключевой фактор в развитии навыка – практика. Не просто делать что-то снова и снова, но ставить себе задачи чуть выше вашего уровня, пытаться их решать, анализируя свою эффективность и исправляя ошибки.»
Mary Poppendieck: «Осознанная практика не значит делать то, в чем вы сильны, это значит бросать себе вызов, делая то, в чем вы слабы. Это не обязательно удовольствие.»
Осознанная практика - это обучение. Обучение, которое меняет вас, обучение, которое меняет ваше поведение. Удачи.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Jon Jagger
97 Вещей, Которые Должен Знать Каждый Программист
22. Занимайтесь Осознанной Практикой
Осознанная практика – это не просто выполнение работы. Если вы спросите себя «Почему я решаю эту задачу?» и ответом будет «Чтобы её решить», то вы не занимаетесь осознанной практикой.
Вы практикуетесь, чтобы улучшить ваш навык решать задачи. Речь идет о мастерстве и технике. Осознанная практика означает повторение. То есть выполнение задания с целью оттачивания мастерства в том или ином аспекте задания. Повторение уже повторенного. Методично, снова и снова, пока вы не достигнете желаемого уровня мастерства. Вы практикуетесь, чтобы отточить мастерство решения задачи, а не просто решить задачу.
Основная цель оплачиваемой разработки - завершить продукт, в то время как основная цель осознанной практики - повысить производительность. Это не одно и то же. Спросите себя, сколько времени вы тратите на разработку чужого продукта? А сколько на саморазвитие?
Сколько практики требуется, чтобы достичь мастерства? Peter Norvig пишет, что «около 10 000 часов… это магическое число». Mary Poppendieck в «Leading Lean Software Development» заметила, что «Хорошему исполнителю потребуется минимум 10 тысяч часов практики, чтобы стать экспертом».
Навык приходит постепенно, не сразу за 10 000 часов! Тем не менее, 10 000 часов это много: около 20 часов в неделю в течение 10 лет. Увидев эти цифры, можно подумать, что достичь уровня эксперта просто невозможно. Это не так. Уровень во многом зависит от осознанного выбора. Выбор за вами. Исследования последних двух десятилетий показали, что основным фактором приобретения опыта является время, затрачиваемое на осознанную практику. Врожденный талант не является основным фактором. По словам Mary Poppendieck: «Практически все исследователи уровня мастерства сходятся в том, что врожденный талант лишь начало. Необходимо иметь самый базовый уровень, чтобы начать. После чего успеха достигают те, кто больше других работает над этим.»
Нет смысла намеренно практиковать то, в чём вы уже являетесь экспертом. Осознанная практика означает практиковать то, в чем вы не очень хороши.
Peter Norvig: «Ключевой фактор в развитии навыка – практика. Не просто делать что-то снова и снова, но ставить себе задачи чуть выше вашего уровня, пытаться их решать, анализируя свою эффективность и исправляя ошибки.»
Mary Poppendieck: «Осознанная практика не значит делать то, в чем вы сильны, это значит бросать себе вызов, делая то, в чем вы слабы. Это не обязательно удовольствие.»
Осознанная практика - это обучение. Обучение, которое меняет вас, обучение, которое меняет ваше поведение. Удачи.
Источник: https://www.oreilly.com/library/view/97-things-every/9780596809515/
Автор оригинала – Jon Jagger
День триста шестьдесят седьмой. #ЗаметкиНаПолях
ASP.NET MVC 5.
HTML Формы
Этот материал может показаться довольно примитивным и не относящимся напрямую к ASP.NET MVC, но, как это ни удивительно, такой простой на первый взгляд элемент HTML, как
Атрибуты Action и Method
Форма - это контейнер для элементов ввода: кнопок, флажков, текстовых полей и многого другого. Элементы ввода в форме позволяют пользователю вводить информацию на страницу и отправлять её на сервер. Но как и на какой сервер? Ответы на эти вопросы находятся в двух наиболее важных атрибутах тега
Атрибут
Когда пользователь отправляет форму с помощью HTTP-запроса GET, браузер берёт имена и значения элементов формы и помещает их в строку запроса. Предыдущая форма отправит браузер по следующему URL-адресу (при условии, что пользователь ввёл «dotnet»):
Вы также можете присвоить атрибуту
Ещё важнее то, что глагол GET семантически правильнее использовать, потому что GET представляет собой идемпотентную операцию только для чтения. То есть вы можете отправлять GET-запрос на сервер сколько угодно раз без каких-либо побочных эффектов, потому что GET не изменяет (по крайней мере, не должен) состояние сервера.
С другой стороны, POST - это тип запроса, который используется для отправки транзакции по кредитной карте, добавления товара в корзину или изменения пароля. Запрос POST обычно изменяет состояние сервера, и повторение запроса может привести к нежелательным последствиям. Многие браузеры помогают пользователю избежать повторения запроса POST, показывая предупреждающее сообщение. Веб-приложения обычно используют GET-запросы для чтения данных и POST-запросы для записи (обновления, создания или удаления) данных.
Удивительно, но мне буквально недавно пришлось объяснять это старшему коллеге, который решил изменить GET-запрос поиска в старой версии сайта на POST-запрос в новой версии по причине большого (относительно) объёма данных формы и длинного URL запроса.
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
ASP.NET MVC 5.
HTML Формы
Этот материал может показаться довольно примитивным и не относящимся напрямую к ASP.NET MVC, но, как это ни удивительно, такой простой на первый взгляд элемент HTML, как
form
, часто используется неверно даже опытными разработчиками.Атрибуты Action и Method
Форма - это контейнер для элементов ввода: кнопок, флажков, текстовых полей и многого другого. Элементы ввода в форме позволяют пользователю вводить информацию на страницу и отправлять её на сервер. Но как и на какой сервер? Ответы на эти вопросы находятся в двух наиболее важных атрибутах тега
form
: action
и method
.Атрибут
action
сообщает браузеру, куда отправлять информацию, поэтому содержит URL-адрес. Он может быть относительным, или абсолютным, если вы хотите отправить информацию в другое приложение или на другой сервер. Следующая форма отправляет поисковый запрос (текстовое поле с именем q
) на страницу поиска Google из любого приложения:<form action="https://www.google.com/search">Тег формы в предыдущем фрагменте кода не включает атрибут
<input name="q" type="text" />
<input type="submit" value="Search!" />
</form>
method
. Атрибут method
сообщает браузеру, какой HTTP метод (POST или GET) использовать при отправке информации. Хотя может показаться, что для отправки информации на сервер значением по умолчанию должно быть post
, на самом деле значением по умолчанию является get
. То первая строчка кода выше эквивалентна следующей:<form action="https://www.google.com/search" method="get">
Когда пользователь отправляет форму с помощью HTTP-запроса GET, браузер берёт имена и значения элементов формы и помещает их в строку запроса. Предыдущая форма отправит браузер по следующему URL-адресу (при условии, что пользователь ввёл «dotnet»):
https://www.google.com/search?q=dotnet
GET или POST?Вы также можете присвоить атрибуту
method
значение post
, и в этом случае браузер помещает данные формы в тело HTTP-запроса. И хотя можно успешно отправить POST-запрос в поисковую систему и получить результаты, GET-запрос предпочтительнее. В отличие от POST, вы можете сохранить запрос GET в закладках, потому что все параметры находятся в URL. Вы можете использовать URL-адрес в качестве гиперссылки в электронной почте или на веб-странице и сохранять при этом все значения формы.Ещё важнее то, что глагол GET семантически правильнее использовать, потому что GET представляет собой идемпотентную операцию только для чтения. То есть вы можете отправлять GET-запрос на сервер сколько угодно раз без каких-либо побочных эффектов, потому что GET не изменяет (по крайней мере, не должен) состояние сервера.
С другой стороны, POST - это тип запроса, который используется для отправки транзакции по кредитной карте, добавления товара в корзину или изменения пароля. Запрос POST обычно изменяет состояние сервера, и повторение запроса может привести к нежелательным последствиям. Многие браузеры помогают пользователю избежать повторения запроса POST, показывая предупреждающее сообщение. Веб-приложения обычно используют GET-запросы для чтения данных и POST-запросы для записи (обновления, создания или удаления) данных.
Удивительно, но мне буквально недавно пришлось объяснять это старшему коллеге, который решил изменить GET-запрос поиска в старой версии сайта на POST-запрос в новой версии по причине большого (относительно) объёма данных формы и длинного URL запроса.
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
День триста шестьдесят восьмой. #DesignPatterns
Паттерны проектирования
11. Паттерн «Абстрактная фабрика» (Abstract Factory)
Фабрика — это второй по популярности паттерн после паттерна «Синглтон». Существуют две классические разновидности фабрик: «Абстрактная фабрика» и «Фабричный метод», предназначенные для инкапсуляции создания объекта или семейства объектов. На практике очень часто отходят от классических реализаций этих паттернов и называют фабрикой любой класс, инкапсулирующий в себе создание объектов.
Назначение: абстрактная фабрика предоставляет интерфейс для создания семейства взаимосвязанных или родственных объектов.
Причины использования:
Когда бизнес-логика программы должна работать с разными видами связанных друг с другом продуктов, не завися от конкретных классов продуктов. Абстрактная фабрика скрывает от клиентского кода подробности того, как и какие конкретно объекты будут созданы. Но при этом клиентский код может работать со всеми типами создаваемых продуктов, поскольку их общий интерфейс был заранее определён.
Классическая диаграмма приведена на рисунке ниже:
-
-
-
-
Основная особенность абстрактной фабрики заключается в том, что она предназначена для создания семейства объектов, что сильно сужает ее применимость. Но в некоторых предметных областях или инфраструктурном коде периодически возникают задачи, которые решаются набором классов: сериализаторы/десериализаторы, классы для сжатия/распаковки, шифрования/дешифрования и т. п.
Приложение должно использовать согласованные типы объектов, и абстрактная фабрика идеально подходит для решения этой задачи. Интерфейс абстрактной фабрики объявляет набор фабричных методов, а конкретная реализация обеспечивает создание этого семейства объектов.
Одной из разновидностей реализации паттерна «Абстрактная фабрика» является обобщённая фабрика, которая позволяет создавать произвольные типы объектов:
Применимость паттерна
Абстрактная фабрика представляет собой слой для полиморфного создания семейства объектов. Её использование подразумевает обязательное наличие двух составляющих: 1) семейства объектов и 2) возможности замены создаваемого семейства объектов во время исполнения.
Иногда необходимость полноценной абстрактной фабрики очевидна с самого начала, но обычно лучше начать с наиболее простого решения и добавить гибкость лишь в случае необходимости.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 9.
Паттерны проектирования
11. Паттерн «Абстрактная фабрика» (Abstract Factory)
Фабрика — это второй по популярности паттерн после паттерна «Синглтон». Существуют две классические разновидности фабрик: «Абстрактная фабрика» и «Фабричный метод», предназначенные для инкапсуляции создания объекта или семейства объектов. На практике очень часто отходят от классических реализаций этих паттернов и называют фабрикой любой класс, инкапсулирующий в себе создание объектов.
Назначение: абстрактная фабрика предоставляет интерфейс для создания семейства взаимосвязанных или родственных объектов.
Причины использования:
Когда бизнес-логика программы должна работать с разными видами связанных друг с другом продуктов, не завися от конкретных классов продуктов. Абстрактная фабрика скрывает от клиентского кода подробности того, как и какие конкретно объекты будут созданы. Но при этом клиентский код может работать со всеми типами создаваемых продуктов, поскольку их общий интерфейс был заранее определён.
Классическая диаграмма приведена на рисунке ниже:
-
AbstractFactory
— объявляет интерфейс (с возможной базовой реализацией) для создания семейства продуктов;-
AbstractProductA
, AbstractProductB
— семейство продуктов, которые будут использоваться клиентом для выполнения своих задач;-
ProductA1
, ProductB1
— конкретные типы продуктов;-
Client
— клиент фабрики, который получает конкретные продукты для реализации своего поведения.Основная особенность абстрактной фабрики заключается в том, что она предназначена для создания семейства объектов, что сильно сужает ее применимость. Но в некоторых предметных областях или инфраструктурном коде периодически возникают задачи, которые решаются набором классов: сериализаторы/десериализаторы, классы для сжатия/распаковки, шифрования/дешифрования и т. п.
Приложение должно использовать согласованные типы объектов, и абстрактная фабрика идеально подходит для решения этой задачи. Интерфейс абстрактной фабрики объявляет набор фабричных методов, а конкретная реализация обеспечивает создание этого семейства объектов.
Одной из разновидностей реализации паттерна «Абстрактная фабрика» является обобщённая фабрика, которая позволяет создавать произвольные типы объектов:
class GenericAbstractFactory {В данном случае абстрактная фабрика становится конфигурируемой, с её помощью можно создавать объект любого или заданного типа (в данном случае
public object Make(string id) { ... }
public IProduct MakeProduct(string id) { ... }
public T MakeGeneric<T>(string id) where T : IProduct { ... }
}
…
var factory = new GenericAbstractFactory();
var o = factory.Make("1");
var p = factory.MakeProduct("2");
var t = factory.MakeGeneric<Product>("3");
IProduct
).Применимость паттерна
Абстрактная фабрика представляет собой слой для полиморфного создания семейства объектов. Её использование подразумевает обязательное наличие двух составляющих: 1) семейства объектов и 2) возможности замены создаваемого семейства объектов во время исполнения.
Иногда необходимость полноценной абстрактной фабрики очевидна с самого начала, но обычно лучше начать с наиболее простого решения и добавить гибкость лишь в случае необходимости.
Источник: Тепляков С. "Паттерны проектирования на платформе .NET." — СПб.: Питер, 2015. Глава 9.
День триста шестьдесят девятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
HTML Helpers. Начало
HTML helpers (помощники) - это методы, которые вы можете вызывать на свойстве
Каждое представление Razor наследует свойство
Методы расширения используются по двум причинам:
1. Они доступны только тогда, когда пространство имён метода расширения находится в области видимости. Все методы расширения MVC для
2. Вы можете создавать собственные методы расширения для замены или дополнения встроенных помощников.
Помощники существуют для любых HTML элементов, используемых в формах:
-
Тем же способом помощники можно использовать в строго типизированных представлениях. Однако для этого больше подойдут строго типизированные помощники. Они отличаются от обычных наличием суффикса For и принимают первым параметром лямбда-выражение для выбора свойства модели. Например, в строго типизированном представлении для отображения класса
Продолжение следует…
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
ASP.NET MVC 5.
HTML Helpers. Начало
HTML helpers (помощники) - это методы, которые вы можете вызывать на свойстве
Html
представления для генерации HTML-разметки. Их цель - облегчить создание представления. Например, помощник BeginForm
можно использовать для создания тега формы для формы поиска (вместо конструкции using
можно использовать помощник EndForm
, закрывающий форму):@using (Html.BeginForm("Search", "Home", FormMethod.Get)) {Скорее всего будет выведена та же разметка, что и в предыдущем посте. Однако за кулисами помощник координирует свою работу с механизмом маршрутизации для создания правильного URL-адреса, поэтому код более устойчив к изменениям и при развертывании приложения.
<input type="text" name="q" />
<input type="submit" value="Search" />
}
Каждое представление Razor наследует свойство
Html
из своего базового класса. Свойство Html
имеет тип System.Web.Mvc.HtmlHelper<T>
, где T
- это тип модели для представления (по умолчанию dynamic
). Однако метод BeginForm
, как и большинство других, определён как метод расширения.Методы расширения используются по двум причинам:
1. Они доступны только тогда, когда пространство имён метода расширения находится в области видимости. Все методы расширения MVC для
HtmlHelper
находятся в пространстве имен System.Web.Mvc.Html
(которое находится в области видимости благодаря ссылке на него в файле Views/web.config
). Вы можете удалить его.2. Вы можете создавать собственные методы расширения для замены или дополнения встроенных помощников.
Помощники существуют для любых HTML элементов, используемых в формах:
-
Label
– метка label
- BeginForm
, EndForm
– форма form
- TextBox
– поле для ввода input type=”text”
- TextArea
– многострочное поле textarea
- CheckBox
- флажок input type=”checkbox”
- RadioButton
– переключатель input type=”radio”
- DropDownList
– выпадающий список select
- ListBox
– список с множественным выбором select multiple
- Hidden
– скрытое поле input type=”hidden”
- Password
– поле пароля input type=”password”
Большинство помощников для полей проверяют наличие значений для отображения в коллекции ViewData (ViewBag). Например, если в методе действия задать:ViewBag.Price = 10.0;а в представлении использовать
@Html.TextBox("Price")то будет выведен следующий HTML код:
<input id="Price" name="Price" type="text" value="10" />Это также работает со свойствами объектов, помещённых в
ViewData
:ViewBag.Product = new Product { Title=”Book”, Price=11 }Строго типизированные помощники
…
@Html.TextBox("Product.Title")
@Html.TextBox("Product.Price")
Тем же способом помощники можно использовать в строго типизированных представлениях. Однако для этого больше подойдут строго типизированные помощники. Они отличаются от обычных наличием суффикса For и принимают первым параметром лямбда-выражение для выбора свойства модели. Например, в строго типизированном представлении для отображения класса
Product
:@model MyStore.Models.Productможно использовать строго типизированные помощники:
@Html.TextBox(m => m.Title)Преимуществами использования строго типизированных помощников являются доступность IntelliSense, проверка ошибок во время компиляции и упрощенный рефакторинг (если вы измените имя свойства в вашей модели, Visual Studio может автоматически изменить код в представлении).
@Html.TextBox(m => m.Price)
Продолжение следует…
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
День триста семидесятый. #ЗаметкиНаПолях
ASP.NET MVC 5.
HTML Helpers. Окончание
Помощники и Метаданные модели
Кроме поиска данных внутри
Шаблонизированные Помощники
Шаблонизированные помощники строят HTML, используя метаданные и шаблон. Метаданные включают в себя информацию о значении модели (его имя и тип), а также метаданные модели (добавляются с помощью аннотаций или поставщика метаданных). В качестве шаблонизированных помощников выступают
Используя шаблонизированные помощники, вы просите среду выполнения подобрать наиболее подходящий элемент для отображения или редактирования. Например,
Помощники
Помощники по Рендерингу
Помощники по рендерингу создают ссылки на другие ресурсы внутри приложения, а также частичные представления.
Html.ActionLink и Html.RouteLink
Метод
Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
ASP.NET MVC 5.
HTML Helpers. Окончание
Помощники и Метаданные модели
Кроме поиска данных внутри
ViewData
, помощники также используют доступные метаданные модели. Например, если свойство модели пометить атрибутом DisplayName
:public class Product {а в представлении использовать помощник
[DisplayName("Название")]
public string Title { get; set; }
…
}
@Html.Label("Title")то будет выведен следующий код HTML:
<label for="Title">Название</label>Помощник запрашивает среду выполнения, доступны ли какие-либо метаданные модели для свойства
Title
, и среда выполнения предоставляет информацию из атрибута DisplayName
. Более подробно об атрибутах модели в следующих постах.Шаблонизированные Помощники
Шаблонизированные помощники строят HTML, используя метаданные и шаблон. Метаданные включают в себя информацию о значении модели (его имя и тип), а также метаданные модели (добавляются с помощью аннотаций или поставщика метаданных). В качестве шаблонизированных помощников выступают
Html.Display
(Html.DisplayFor
) и Html.Editor
(Html.EditorFor
), а также их аналоги для целой модели Html.DisplayForModel
и Html.EditorForModel
.Используя шаблонизированные помощники, вы просите среду выполнения подобрать наиболее подходящий элемент для отображения или редактирования. Например,
EditorFor
сгенерирует тот же код HTML, что и TextBoxFor
. Однако, его можно настроить с помощью аннотаций. Например, следующая аннотация:[DataType(DataType.MultilineText)]Приведёт к тому, что
public string Title { get; set; }
EditorFor
сгенерирует многострочное поле textarea
.Помощники
DisplayForModel
и EditorForModel
создают HTML-код для целой модели. Используя их, вы можете добавлять новые свойства в модель и мгновенно видеть изменения в пользовательском интерфейсе, не внося никаких изменений в представления.Помощники по Рендерингу
Помощники по рендерингу создают ссылки на другие ресурсы внутри приложения, а также частичные представления.
Html.ActionLink и Html.RouteLink
Метод
ActionLink
визуализирует гиперссылку на другой метод действия или контроллер. Он использует API маршрутизации для создания URL-адреса. @Html.ActionLink("Ссылка", "AnotherAction")Это производит следующую разметку для маршрута по умолчанию:
<a href="/Home/AnotherAction">Ссылка</a>Помощник
RouteLink
следует тому же шаблону, но также принимает имя маршрута и не имеет аргументов для контроллера и метода действия:@Html.RouteLink("Ссылка", new {action="AnotherAction"})Html.Partial и Html.RenderPartial
Partial
визуализирует частичное представление. Как правило, оно содержит общую разметку, которую вы хотите отобразить в нескольких представлениях:@Html.Partial("ProductDisplay")Здесь указано только имя представления. Среда выполнения ищет нужное представление, используя все доступные механизмы. Кроме того, методу можно передать модель и коллекцию
ViewData
.RenderPartial
похож на Partial
, но он пишет код непосредственно в выходной поток. По этой причине RenderPartial
нужно помещать внутрь блока кода. Следующие две строки приведут к одинаковому выводу в выходной поток:@{ Html.RenderPartial("ProductDisplay"); }Html.Action и Html.RenderAction
@Html.Partial("ProductDisplay")
Action
и RenderAction
аналогичны Partial
и RenderPartial
. Но, тогда как Partial отображает код из другого представления, Action
, выполняет другой метод контроллера и отображает его результат. Action
предлагает больше гибкости, потому что метод контроллера может построить другую модель и использовать другой контекст:[ChildActionOnly]В представлении:
public ActionResult Menu() {
var menu = GetMenuFromSomewhere();
return PartialView(menu);
}
@Html.Action("Menu")Обратите внимание, что метод-действие
Menu
помечен атрибутом ChildActionOnly
. Атрибут не позволяет среде выполнения вызывать метод напрямую через URL. Он может быть вызван только через Action
или RenderAction
. Атрибут ChildActionOnly
не требуется, но обычно рекомендуется для дочерних методов-действий.Источник: Jon Galloway “Professional ASP.NET MVC 5”. – John Wiley & Sons Inc., 2014. Глава 5.
День триста семьдесят первый. #NetInternals
3. Можно ли использовать методы расширения с dynamic?
Нет. Код можно проверить здесь
Источник: Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/
3. Можно ли использовать методы расширения с dynamic?
Нет. Код можно проверить здесь
using System;Это потому, что методы расширения компилируются в статические. Код выше фактически компилируется в это:
public class Program {
public static void Main() {
int x = 5;
x.Extend();
dynamic y = x;
y.Extend();
}
}
static class Foo {
public static void Extend(this int x) {
Console.WriteLine(x);
}
}
IL_0004: call void Foo::Extend(int32)В C# вы могли бы написать его как:
Foo.Extend(x);Однако DLR (Динамическая Среда Выполнения) ищет методы объекта во время выполнения, поэтому вы не можете использовать расширения с динамическими переменными.
Источник: Adam Furmanek «.NET Internals Cookbook» - https://blog.adamfurmanek.pl/