{"id":330481,"date":"2022-03-10T15:00:33","date_gmt":"2022-03-10T15:00:33","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=330481"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=330481","title":{"rendered":"<span>C# \u0414\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u00ab\u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432\u00bb \u0434\u043b\u044f \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0439. \u0427\u0430\u0441\u0442\u044c 1<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/994\/567\/454\/9945674547059c05b716831acc86ef50.png\" alt=\"Splash \u044d\u043a\u0440\u0430\u043d \u043c\u043e\u0435\u0439 \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0439\" title=\"Splash \u044d\u043a\u0440\u0430\u043d \u043c\u043e\u0435\u0439 \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0439\" width=\"700\" height=\"450\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/994\/567\/454\/9945674547059c05b716831acc86ef50.png\"\/><figcaption>Splash \u044d\u043a\u0440\u0430\u043d \u043c\u043e\u0435\u0439 \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0439<\/figcaption><\/figure>\n<p>\u0411\u043b\u0438\u0436\u0435 \u043a \u0434\u0435\u043b\u0443, \u0433\u043e\u0441\u043f\u043e\u0434\u0430: \u0443\u0437\u043d\u0430\u0432 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043e\u0439 \u0438\u043d\u0441\u0442\u0438\u0442\u0443\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u043a\u043e\u043d\u043a\u0443\u0440\u0441 \u043d\u0430 \u043b\u0443\u0447\u0448\u0438\u0435 \u043a\u0443\u0440\u0441\u043e\u0432\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0440\u0435\u0434\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0443\u0440\u0441\u0430, \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0437\u0430\u0439\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e. \u041c\u043e\u0438 \u0441\u0430\u043c\u044b\u0435 \u043a\u0440\u0443\u0442\u044b\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 React, \u043a\u0442\u043e-\u0442\u043e Django, \u0430 \u043a\u0442\u043e-\u0442\u043e Tkinter. <\/p>\n<p>\u0412\u0441\u0435\u043c \u043d\u0430\u043c \u0434\u0430\u043b\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0435\u043c\u044b. \u0412 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043c\u043e\u0438\u043c \u043e\u0434\u043d\u043e\u0433\u0440\u0443\u043f\u043f\u043d\u0438\u043a\u0430\u043c \u0434\u0430\u043b\u0438 \u0447\u0435\u0442\u043a\u043e\u0435 \u0422\u0417 \u0432 \u0432\u0438\u0434\u0435 word, \u0442\u043e \u043c\u043d\u0435 \u0434\u0430\u043b\u0438 \u043f\u0430\u0440\u0443 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439:<\/p>\n<blockquote>\n<p>&#171;<em>\u0421\u043e\u0437\u0434\u0430\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0439, \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:  \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0440\u0435\u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e \u0441\u0443\u0431\u0431\u043e\u0442\u0430\u043c, \u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e \u043e\u0431\u0435\u0434\u0430.<\/em>&#187; <\/p>\n<\/blockquote>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d, \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u0436\u0435. \u041d\u043e \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0447\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u043b\u043e, \u0438 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u0440\u0438\u0448\u043b\u0430 \u043c\u044b\u0441\u043b\u044c : <\/p>\n<blockquote>\n<p>&#171;\u042f \u0441\u043e\u0437\u0434\u0430\u043c \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a <s>\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/s> \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438, \u0441 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0435\u0439 \u0438 \u043f\u0430\u0439\u0442\u043e\u043d\u043e\u043c!&#187;<\/p>\n<\/blockquote>\n<h2>\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441<\/h2>\n<p>\u0414\u0430, \u044f \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u044e \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434, \u0438 \u043c\u043d\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e, \u0432\u0435\u0434\u044c \u044f \u043f\u043e\u043a\u0430 \u0443\u0447\u0443\u0441\u044c. \u041d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e-\u0442\u0430\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441, \u0438 \u044f \u0435\u0433\u043e \u043f\u043e\u0437\u0430\u0438\u043c\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0443 \u043a\u043e\u043c\u0430\u043d\u0434 \u043c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442\u0430:<\/p>\n<pre><code class=\"cs\">\/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430 \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b\u043e \u043c\u0430\u043b\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441:<\/p>\n<pre><code>\/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430[\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04301=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04351;\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04302=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04352;....] \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0432\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u0435, \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0435\u0433\u0438 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430.<\/p>\n<pre><code>\/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430 \/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430[\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04301=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04351;\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04302=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04352;....]<\/code><\/pre>\n<p>\u0418 \u0438\u043c\u044f \u044d\u0442\u043e\u043c\u0443 \u044f\u0437\u044b\u043a\u0443 &#8212; StackMarkup. \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0432 StackLayout \u0438 \u0442\u0430\u043a \u0436\u0435, \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c <strong><em>ToLower() <\/em><\/strong>\u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a, \u0447\u0442\u043e \u0431\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043d\u0435 \u0438\u043c\u0435\u043b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u043b\u0430\u043d\u044b \u043d\u0430 \u044d\u0442\u043e\u0442 \u044f\u0437\u044b\u043a, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0430\u043c\u044b\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 &#8212; \u044d\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/p>\n<pre><code class=\"cs\">public class MarkupConfiguration {         public char? BeforeCharacter { get; set; } = '\/';         public bool CustomPropertyParser { get; set; } }<\/code><\/pre>\n<p>\u0414\u0430, \u0442\u0443\u0442 \u043d\u0435 \u0433\u0443\u0441\u0442\u043e, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c &#8212; \u044d\u0442\u043e \u043b\u0438\u0448\u044c \u0437\u0430\u0434\u0435\u043b \u043d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435.<\/p>\n<p>\u0412\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442: \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b (\u043d\u0443 \u043a\u0440\u043e\u043c\u0435 object \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435). \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0430\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0432\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430:<\/p>\n<pre><code class=\"cs\">\/\/\/&lt;summary> \/\/\/ \u0414\u0430\u0435\u0442 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c(\u0438\u043b\u0438 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b) \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \/\/\/&lt;\/summary> [AttributeUsage(AttributeTargets.Property |                  AttributeTargets.Class |                  AttributeTargets.Struct)] public class MarkupAliasesAttribute: Attribute  {     \/\/\u0415\u0441\u043b\u0438 \u044f \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0441\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0442\u043e \u044f \u043f\u043e\u043c\u0435\u0447\u0430\u044e \u0435\u0435 \u043a\u0430\u043a readonly     \/\/\u0415\u0441\u043b\u0438 \u044f \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0441\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0442\u043e \u0435\u0435 \u0442\u0438\u043f \u0432\u0441\u0435\u0433\u0434\u0430 IReadOnly     public readonly IReadOnlyList&lt;string> aliases;     public MarkupAliasesAttribute(params string[] aliases)     {         var list = new List&lt;string>();         foreach(var alias in aliases)\/\/ \u041a \u0447\u0435\u0440\u0442\u0443 Linq \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c foreach!         {             list.Add(alias.Trim().ToLower());         }         this.aliases = list.AsReadOnly();     } }  \/\/\/&lt;summary> \/\/\/ \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0442\u043e\u0447\u043d\u0435\u0435 \u0435\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0437\u0430\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 Markup \/\/\/&lt;\/summary> [AttributeUsage(AttributeTargets.Property)] public class MarkupIgnoreAttribute: Attribute {}<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435, \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b \u043f\u043e\u043b\u043e\u043c\u0430\u044e\u0442 \u0432\u0435\u0441\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441. \u041d\u043e \u044d\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0435 \u0437\u0434\u0435\u0441\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0438\u043c\u0435\u044e\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 &#171;\u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438&#187;. \u0414\u0430\u043b\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f :<\/p>\n<pre><code class=\"cs\">\/\/\/&lt;param> \/\/\/ \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \/\/\/&lt;param> public class AliasException: Exception {     \/\/ \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435     \/\/ \u0440\u0435\u0433\u044d\u043a\u0441, \u043c\u044b \u043f\u0440\u043e\u043f\u0438\u0448\u0435\u043c \u0435\u0433\u043e \u043a\u0430\u043a static readonly \u0447\u0442\u043e \u0440\u0430\u0432\u043d\u043e\u0441\u0438\u043b\u044c\u043d\u043e \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0435     \/\/ \u0442\u0430\u043a \u0436\u0435 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0443\u043a\u0430\u0436\u0435\u043c RegexOptions.Compiled, \u0442\u0430\u043a \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c      \/\/ \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043e\u0434\u043d\u0430\u043a\u0430 \u0435\u0433\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0439,      \/\/ \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0447\u0430\u0441\u0442\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c     private static readonly Regex _isLetterOnly = new Regex(@\"^[a-zA-Z]+$\",                                                             RegexOptions.Compiled);     \/\/\/&lt;param>     \/\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438\u043c\u044f \u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0438\u043c\u044f \u043d\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435     \/\/\/&lt;\/param>     public static void CheckNaming(string alias, MarkupConfiguration configuration)     {         if(alias.Contains(' '))         {             throw new AliasException($\"\u0418\u043c\u044f {alias} \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b\u044b!\");         }         if(!_isLetterOnly.IsMatch(alias))         {             throw new AliasException($\"\u0418\u043c\u044f {alias} \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b!\");         }     }     public AliasException(string message):base(message){} }  \/\/\/&lt;param> \/\/\/ \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \/\/\/&lt;param> public class SyntaxException: Exception {     public static void CheckIsEmptyName(string substring)     {         if(string.IsNullOrWhiteSpace(substring))         {             throw new SyntaxException(\"\u0418\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c!\");         }     }     public SyntaxException(string message): base(message) {} }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u0435\u043d \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443( \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0444\u0430\u0439\u043b\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043e\u0434 StackMarkup). \u042f \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b Antrl, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b \u0435\u0433\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043e\u0449\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u041d\u0435 \u043f\u0443\u0433\u0430\u0439\u0442\u0435\u0441\u044c \u0442\u0430\u043a\u043e\u0433\u043e &#171;\u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e&#187; \u043a\u043e\u0434\u0430, \u0443\u043c\u0435\u043b \u0431\u044b \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c RegEx \u043e\u043d \u0431\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0431\u044b \u043a\u043e\u0440\u043e\u0447\u0435&#8230;.<\/p>\n<details class=\"spoiler\">\n<summary>MarkupParsedRow.cs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public class MarkupParsedRow {     \/\/ \u0414\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0433\u044d\u043a\u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d \u043b\u0438 \u0442\u0435\u0433 \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c(\u0438) \u0438\u043b\u0438 \u0431\u0435\u0437     private static readonly Regex _elementWithProperties = new Regex(         @\"[a-zA-Z]+\\[[^\\]]*\\](\\.[^\\]]*\\])?\",          RegexOptions.Compiled     );      public MarkupParsedRow(string row, MarkupConfiguration configuration)     {         if(configuration.BeforeCharacter != null)         {             SetCountBeforeCharacter(row, configuration);         }                  \/\/ \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \"\/\")         row = row.Remove(0, CountBeforeCharacter);                \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u0435\u0441\u043b\u0438 i=-1 \u0437\u043d\u0430\u0447\u0438\u0442 \u044d\u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430         int i = 0;         while (row.IndexOf(' ', i) &lt; row.IndexOf(']'))         {             i = row.IndexOf(' ', i+1);             if (i == -1)             {                 break;             }         }          if (i!= -1) \/\/ \u0435\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442         {             \/\/ defination \u0442\u0430 \u0436\u0435 \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u043e \u0441 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430             var defination = row.Substring(0, row.IndexOf(' ', i));                          SyntaxException.CheckIsEmptyName(defination);             \/\/ \u0435\u0441\u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0442\u043e \u0443\u0441\u0442\u043e\u043d\u0430\u0432\u043b\u0438\u0432\u0435\u043c \u0438 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u0438 \u0438\u043c\u044f,              \/\/ \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430             if(_elementWithProperties.IsMatch(defination))             {                 SetNameAndProperty(defination, configuration);                 Content = row.Replace($\"{MarkupElementName}[{PropertiesString}] \", \"\");             }             else             {                 \/\/ \u0435\u0441\u043b\u0438 \u0436\u0435 \u043d\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442 defination \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u044f                 MarkupElementName = defination;                 AliasException.CheckNaming(MarkupElementName, configuration);                 Content = row.Replace($\"{MarkupElementName} \", \"\");             }         }         \/\/ \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u043d\u043e \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430         else if (_elementWithProperties.IsMatch(row))          {             SetNameAndProperty(row, configuration);         }         \/\/ \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u044f         else          {             SyntaxException.CheckIsEmptyName(row);             MarkupElementName = row;         }          MarkupElementName = MarkupElementName.ToLower().Trim();     }     \/\/ \u0417\u0430\u0434\u0435\u043b \u043d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435     public int CountBeforeCharacter { get; private set; } = 0;      \/\/ \u0418\u043c\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430     public string MarkupElementName { get; private set; }      \/\/ \u0421\u0442\u0440\u043e\u043a\u0430 \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0435\u0441\u0442\u044c     public string? PropertiesString { get; private set; }     \/\/ \u041a\u043e\u043d\u0442\u0435\u043d\u0442, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0441\u0442\u044c     public string? Content { get; private set; }      private void SetCountBeforeCharacter(string row, MarkupConfiguration configuration)     {         foreach(var character in row)         {             if(character == configuration.BeforeCharacter)             {                 CountBeforeCharacter += 1;                 continue;             }             break;         }     }     \/\/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0418\u043c\u044f \u0438 \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430      private void SetNameAndProperty(string defination, MarkupConfiguration configuration)     {         MarkupElementName = defination.Substring(0, defination.IndexOf('['));         PropertiesString = defination.Substring(             defination.IndexOf('[') + 1,             defination.IndexOf(']') - defination.IndexOf('[') -1         );         AliasException.CheckNaming(MarkupElementName, configuration);     }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0433\u0447\u0435. \u041d\u0443\u0436\u0435\u043d \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0437 MarkupParsedRow \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442. \u0412\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0435\u0441\u0442\u044c, \u0447\u0442\u043e net 5 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435 \u043d\u0430\u0434\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b. <\/p>\n<p>\u041e\u0434\u043d\u043e \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 &#8212; \u044d\u0442\u043e <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.componentmodel.typedescriptor\" rel=\"noopener noreferrer nofollow\"><strong>TypeDescriptor<\/strong><\/a>, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/www.hanselman.com\/blog\/typeconverters-theres-not-enough-typedescriptergetconverter-in-the-world\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>. <\/p>\n<p>\u0410 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u043d\u0435 \u0434\u0430\u0436\u0435 \u043d\u0435 \u043d\u0430\u0434\u043e : \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430 \u043c\u0435\u043d\u044f <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.data.common.dbconnectionstringbuilder\" rel=\"noopener noreferrer nofollow\"><strong>DbConnectionStringBuilder<\/strong><\/a><\/p>\n<p>\u042d\u0442\u043e \u0435\u0449\u0435 \u043d\u0435 \u0432\u0441\u0435. \u0422\u0430\u043a \u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.activator\" rel=\"noopener noreferrer nofollow\"><strong>Activator<\/strong><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0442\u0438\u043f\u0430.<\/p>\n<pre><code class=\"cs\">public class MarkupElementDefination {         \/\/ \u0422\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         private readonly Type _elementType;         \/\/ \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         private readonly Dictionary&lt;string, PropertyInfo> _properties = new Dictionary&lt;string, PropertyInfo>();         \/\/ \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430         private readonly MarkupConfiguration _configuration;         \/\/ \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442         private readonly PropertyInfo _content = null;                  \/\/ \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442         public MarkupElementDefination(Type elementType, MarkupConfiguration configuration)         {             _elementType = elementType;             _configuration = configuration;             \/\/ \u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430             foreach(var property in elementType.GetProperties())             {                 \/\/ \u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 MarkupIgnore, \u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e                 if(property.GetCustomAttribute&lt;MarkupIgnoreAttribute>() != null)                 {                     continue;                 }                 \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430                 foreach(var attribute in property.GetCustomAttributes())                 {                     \/\/ \u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 MarkupAliases, \u0442\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c                     \/\/ \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b \u0434\u043b\u044f \u043d\u0435\u0433\u043e                     if(attribute is MarkupAliasesAttribute aliasesAtr)                     {                         SettingAliases(property, aliasesAtr.aliases);                     }                     \/\/ \u0415\u0441\u043b\u0438 \u0442\u0435\u0433 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442                     if(attribute is MarkupContentAttribute)                     {                         if(property.PropertyType != typeof(string))                         {                             throw new InvalidOperationException(\"Content \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0442\u0438\u043f\u0430!\");                         }                         else                         {                             CanContainContent = true;                             _content = property;                         }                     }                 }                 _properties.Add(property.Name.Trim().ToLower(), property);             }         }         \/\/ \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442         public bool CanContainContent { get; }             \/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u043c\u0435\u043d\u0430 \u0434\u043b\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432         private void SettingAliases(PropertyInfo property, IReadOnlyList&lt;string> aliases)         {             foreach(var alias in aliases)             {                 AliasException.CheckNaming(alias, _configuration);                 try                 {                     _properties.Add(alias, property);                 }                 catch(ArgumentException)                 {                     throw new AliasException($\"\u0418\u043c\u044f {alias} \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442\u043e!\");                 }             }         }            \/\/ \u041f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443, \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0437 \u043d\u0435\u0435 \u043e\u0431\u044a\u0435\u043a\u0442         public object BuildElement(MarkupParsedRow row)         {             \/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u0442\u0438\u043f\u0430              var element  = Activator.CreateInstance(_elementType);             var properties = new DbConnectionStringBuilder();                       if (!_configuration.CustomPropertyParser)             {                  if (!string.IsNullOrWhiteSpace(row.PropertiesString))                 {                     try                     {                         properties.ConnectionString = row.PropertiesString;                     }                     catch (ArgumentException)                     {                         throw new SyntaxException(\"\u041d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\");                     }                 }                 \/\/ \u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u043f\u043e \u0432\u0441\u0435\u043c \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c                 foreach (var propertyName in properties.Keys)                 {                     var propName = ((string)propertyName).Trim().ToLower();                     if (_properties.ContainsKey(propName))                     {                         var value = GetConvertedTypeFromString(                             _properties[propName].PropertyType,                             (string)properties[propName]                         );                         _properties[propName].SetValue(element, value);                     }                     else                     {                         throw new InvalidCastException($\"\u041d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e {propName}\");                     }                 }             }              if(CanContainContent)             {                 _content.SetValue(element, row.Content);             }              return element;         }         \/\/ \u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0432\u043d\u0443\u0436\u043d\u044b\u0439 \u0442\u0438\u043f \u043e\u0431\u044a\u0435\u043a\u0442\u0430          private static object GetConvertedTypeFromString(Type type, string value)         {             var converter = TypeDescriptor.GetConverter(type);             return converter.ConvertFromInvariantString(value);         }     }<\/code><\/pre>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e.<\/p>\n<p>\u041d\u043e, \u043a\u0430\u043a \u0432\u044b \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u0442\u0443\u0442 \u043d\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438\u043c\u0435\u043d\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430. \u0422\u043e \u0435\u0441\u0442\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0437\u0430\u043f\u0438\u0445\u043d\u0443\u0442\u044c \u0442\u0443\u0434\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0442\u0435\u043c\u0438 \u0436\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438, \u0438 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043d\u0430 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0442\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0447\u0438\u0442\u0430\u0435\u043c, \u043e\u0431\u044f\u0437\u0430\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u0432\u0441\u0435\u043c \u044d\u0442\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u043e\u043d, \u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 &#171;MarkupDocument&#187;. \u0418 \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u0432\u043e\u043f\u0440\u043e\u0441 \u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438\u043c\u0435\u043d\u0438 \u0443 \u0432\u0430\u0441 \u043e\u0442\u043f\u0430\u043b. <\/p>\n<p>\u041d\u043e \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430? \u042d\u0442\u043e \u0442\u043e\u0436\u0435 \u043b\u0435\u0433\u043a\u043e \u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Generic&#8217;\u043e\u0432 : \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0438\u0448\u0435\u043c <strong><em>where T: new()<\/em><\/strong>  (\u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0447\u0442\u043e \u0442\u0438\u043f \u043e\u0431\u044f\u0437\u0430\u043d \u0438\u043c\u0435\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0435\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432). \u0415\u0449\u0435 \u043e\u0434\u0438\u043d \u043f\u043b\u044e\u0441 Generic&#8217;\u043e\u0432 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043d\u0435 \u043a\u0443\u0434\u0430 \u043f\u0440\u0438\u044f\u0442\u043d\u0435\u0435 \u043f\u0438\u0441\u0430\u0442\u044c <code>&lt;Type><\/code> \u0447\u0435\u043c  <code>typeof(Type)<\/code><\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043e <strong><em>StreamReader<\/em><\/strong>. \u0415\u0433\u043e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u0430\u0436\u0434\u0443\u044e \u043b\u0438\u043d\u0438\u044e, \u0442\u043e \u0435\u0441\u0442\u044c \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <strong><em>ReadLine()<\/em><\/strong><\/p>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u043e\u0433\u0434\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d:<\/p>\n<pre><code class=\"cs\">public delegate    void MarkupElementBuildedHandler(object element, MarkupParsedRow parsedRow);<\/code><\/pre>\n<pre><code class=\"cs\">namespace StackMarkup {     public class MarkupDocument: IEnumerable     {         \/\/ \u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b         private readonly List&lt;Type> _registered = new List&lt;Type>();         \/\/ \u0425\u0440\u0430\u043d\u0438\u0442 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b-\u0438\u043c\u0435\u043d\u0430, \u0438 \u0441\u0430\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         private readonly Dictionary&lt;string, MarkupElementDefination>               _elements = new Dictionary&lt;string, MarkupElementDefination>();          \/\/ \u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u043a\u043e\u0433\u0434\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0443\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u043d         public event MarkupElementBuildedHandler OnMarkupElemenBuilded;          public MarkupDocument() { }          public MarkupDocument(MarkupConfiguration configuration)         {             Configuration = configuration;         }          public MarkupConfiguration Configuration { get; set; } = new MarkupConfiguration()         {             BeforeCharacter = '\/'         };                  \/\/ \u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442,         \/\/ \u044d\u0442\u043e\u0442 \u043b\u0438\u0441\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430,         \/\/ \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u0430\u043c\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0437\u0430\u0440\u0435\u0433\u0435\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432         public List&lt;object> Elements { get; } = new List&lt;object>();                  \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435          public void Register&lt;T>() where T: new()  \/\/ \u042d\u0442\u043e \u043f\u0440\u043e \u0442\u043e \u0447\u0442\u043e \u044f \u0433\u043e\u0432\u043e\u0440\u0438\u043b!         {             var type = typeof(T);              if(_registered.Contains(type))             {                 throw new ArgumentException(\"\u0422\u0438\u043f \u0443\u0436\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d!\");             }                          \/\/ \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u0430\u043c\u0430 \u0447\u0438\u0442\u0430\u0435\u0442 \u0442\u0438\u043f             var markupElementDefination =                  new MarkupElementDefination(type, Configuration);                              \/\/ \u0415\u0441\u043b\u0438 \u0442\u0438\u043f \u0441\u043e\u0434\u0435\u0436\u0440\u0438\u0442\u0442 \u0430\u0440\u0442\u0438\u0431\u0443\u0442 MarkupAliases, \u0442\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u0438\u043c\u0435\u043d\u0430 \u0442\u043e\u0436\u0435             if (type.GetCustomAttribute&lt;MarkupAliasesAttribute>() != null)             {                 var attr = type.GetCustomAttribute&lt;MarkupAliasesAttribute>();                 foreach (var alias in attr.aliases)                 {                     AliasException.CheckNaming(alias.Trim().ToLower(),                          Configuration);                      if(_elements.ContainsKey(alias.Trim().ToLower()))                     {                         throw new AliasException(                             $\"\u0418\u043c\u044f {alias.Trim().ToLower()} \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442\u043e!\");                     }                      _elements.Add(alias.Trim().ToLower(),                          markupElementDefination);                 }             }             \/\/ \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0438\u043c\u0435\u043d\u0430 \u0438 \u043f\u0441\u0435\u0432\u043e\u0434\u043e\u043d\u0438\u043c\u044b             _elements.Add(type.Name.Trim().ToLower(), markupElementDefination);         }                           public void Load(string path)         {             using(var reader = new StreamReader(path))             {                 \/\/ \u041f\u043e\u043a\u0430 \u0444\u0430\u0439\u043b \u043d\u0435 \u043a\u043e\u043d\u0447\u0438\u043b\u0441\u044f                 while (reader.Peek() >= 0)                 {                     \/\/ \u041f\u0430\u0440\u0441\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u0443                     var row = new MarkupParsedRow(reader.ReadLine(), Configuration);                      if(!_elements.ContainsKey(row.MarkupElementName))                     {                         throw new AliasException($\"\u0418\u043c\u044f {row.MarkupElementName} \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442\");                     }                     \/\/                     var element = _elements[row.MarkupElementName].BuildElement(row);                     \/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435                     OnMarkupElemenBuilded?.Invoke(element, row);                     Elements.Add(element);                 }             }         }                  \/\/\u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430         public IEnumerator GetEnumerator()         {             return Elements.GetEnumerator();         }     } }<\/code><\/pre>\n<h2>\u041e\u043f\u0438\u0442\u043e\u043d\u0438\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>\u0414\u0430, \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u043d\u043e \u0432\u0441\u0435 \u0436\u0435. \u0422\u0435\u043f\u0435\u0440\u044c \u0431\u0438\u043b\u0434\u0438\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438 \u0432\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 python, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.nuget.org\/packages\/IronPython.StdLib\/3.4.0-alpha1\" rel=\"noopener noreferrer nofollow\">IronPython<\/a> (\u042f \u043d\u0430\u0437\u0432\u0430\u043b \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044f\u043c\u0438).<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0441\u0430\u043c\u0438 \u0442\u0435\u0433\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>TraditionMarkup.cs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace ScheduleGenerator.Traditions {      public abstract class BaseMarkup     {         public static MarkupDocument Document { get; } = GetDocument();                \/\/ \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0441\u0430\u043c\u043e \u043f\u043e \u0441\u0435\u0431\u0435 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044f \u0434\u043e\u0440\u043e\u0433\u043e\u0441\u0442\u043e\u044e\u0449\u0430\u044f          \/\/ \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u0430\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0441\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044c\u0448\u0435         private static MarkupDocument GetDocument()         {             var doc = new MarkupDocument();              doc.Register&lt;TextMarkup>();             doc.Register&lt;ButtonMarkup>();             doc.Register&lt;NumericUpDownMarkup>();              return doc;         }          public virtual string Name { get; set; }         [MarkupContent]         public virtual string Content { get; set; }         public virtual string Style          {              get             {                 return style == null ? \"nothing\" : style;             }             set => style = value;         }         private string style;          public abstract Control Render();     }      [MarkupAliases(\"text\")]     public class TextMarkup : BaseMarkup     {         [MarkupAliases(\"text\",\"txt\",\"t\")]         public override string Content { get; set; }          public override Control Render()         {             return new TextBlock()             {                 Text = Content,                 Classes = Classes.Parse(Style)             };         }     }      [MarkupAliases(\"btn\",\"button\")]     public class ButtonMarkup : BaseMarkup     {         public override Control Render()         {             return new Button()             {                 Content = Content,                 Classes = Classes.Parse(Style),             };         }     }      [MarkupAliases(\"numbox\")]     public class NumericUpDownMarkup: BaseMarkup     {         public double Value { get; set; }         [MarkupAliases(\"inc\")]         public double Increment { get; set; }         public double Min { get; set; }         public double Max { get; set; }         [MarkupAliases(\"format\")]         public NumberStyles NumberStyle { get; set; }          public override Control Render()         {             return new NumericUpDown()             {                 ParsingNumberStyle = NumberStyle,                 Value = Value,                 Increment = Increment,                 Minimum = Min,                 Maximum = Max             };         }     }      [MarkupAliases(\"textbox\")]     public class TextBoxMarkup: BaseMarkup     {         [MarkupAliases(\"text\", \"txt\", \"t\")]         public override string Content { get; set; }         [MarkupAliases(\"wtk\")]         public string Watermark { get; set; }          public override Control Render()         {             return new TextBox()             {                 Text = Content,                 Watermark = Watermark,                 Classes = Classes.Parse(Style),             };         }     }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d\u044b.<\/p>\n<details class=\"spoiler\">\n<summary>PythonTradition.cs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace ScheduleGenerator.Traditions {     public class PythonTradition : ITradition     {         public readonly static ScriptEngine python;          \/\/ \u0421\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437,          \/\/ \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u044c\u0441\u044f \u0434\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434\u043e\u0432,         \/\/ \u043f\u043e\u043b\u0435\u0439 \u0438\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432.         static PythonTradition()         {             python = Python.CreateEngine();             python.Runtime.Globals.SetVariable(\"App\", App.Instance);         }                  \/\/ \u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b StackMarkup         public IEnumerable&lt;BaseMarkup> Markup { get; private set; }         public string Name { get; private set; } = \"Not defined\";         public string Description { get; private set; } = \"Not defined\";         public ScriptScope PythonScope { get; private set; } = python.CreateScope();         private readonly string _markupPath;         private readonly string _pythonPath;          public PythonTradition(string markupPath, string pythonPath)         {             _markupPath = markupPath;             _pythonPath = pythonPath;              PythonScope.SetVariable(\"__id__\", id);              LoadFiles();         }                  public void Refresh() => LoadFiles();                  private void LoadFiles()         {             \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438,              \/\/ \u0438\u043d\u0430\u0447\u0435 IronPython \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u0438 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0442\u043e\u043b\u044c\u043a\u043e             \/\/ \u0432 \u043f\u0430\u043f\u043a\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0430 \u043d\u0435 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438             var pathes = python.GetSearchPaths();             pathes.Add(Directory.GetDirectoryRoot(_pythonPath));             python.SetSearchPaths(pathes);                          \/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u0430\u0439\u0442\u043e\u043d\u0430             PythonScope = python.ExecuteFile(_pythonPath, PythonScope);              var doc = BaseMarkup.Document; \/\/              doc.Elements.Clear();             doc.Load(_markupPath);              Markup = doc.Elements.Cast&lt;BaseMarkup>();              pathes.Remove(Directory.GetDirectoryRoot(_pythonPath));             python.SetSearchPaths(pathes);              if(PythonScope.ContainsVariable(\"__name__\"))             {                 Name = PythonScope.GetVariable&lt;string>(\"__name__\");             }             if(PythonScope.ContainsVariable(\"__description__\"))             {                 Description = PythonScope.GetVariable&lt;string>(\"__description__\");             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u044f \u044d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0430\u0441\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d:<\/p>\n<details class=\"spoiler\">\n<summary>TraditionsMoreVm.cs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace ScheduleGenerator.ViewModels {     using Traditions;      public class TraditionsMoreVm : ViewModelBase, IRoutableViewModel     {         \/****************         \u0417\u0434\u0435\u0441\u044c \u0438\u0434\u0435\u0442 \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441 \u043d\u0435 \u043a\u0430\u0441\u0430\u0435\u0442\u044c\u0441\u044f         *****************\/          public TraditionsMoreVm(IScreen screen, ITradition tradition)         {             HostScreen = screen; \/\/\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0439\u0442\u0435, \u044d\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 RxUI             var stack = new StackPanel() {Spacing = 5};             try             {                 foreach(var element in tradition.Markup)                 {                     var rendered = element.Render();                     \/\/ \u0415\u0441\u043b\u0438 \u0438\u043c\u044f \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0435 \u0442\u043e, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0435                     if(!string.IsNullOrWhiteSpace(element.Name) &amp;&amp;                         tradition.                         PythonScope.                         ContainsVariable($\"observe_{element.Name}\"))                      {                         \/\/ \u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u0435                         dynamic observe = tradition.PythonScope.GetVariable($\"observe_{element.Name}\");                         observe(rendered, this);                     }                     stack.Children.Add(rendered);                 }                 Control = stack;             }             catch             {                 App.ErrorMessageBox(\"\u041e\u0448\u0438\u0431\u043a\u0430\", \"\u041e\u0448\u0438\u0431\u043a\u0430 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438\",                      () => screen.Router.NavigateBack.Execute()                 );             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0432 \u0442\u043e\u0439 \u0436\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0433\u0434\u0435 \u0438 \u043f\u0440\u043e\u0435\u043a\u0442, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0430\u0439\u043b references.py . \u042d\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0442 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 (\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0447\u0435\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0441\u0430\u043c\u0438 \u043d\u0443\u0436\u043d\u044b\u0435 \u0432\u0430\u043c \u043c\u043e\u0434\u0443\u043b\u0438).<\/p>\n<pre><code class=\"python\">import clr  clr.AddReference(\"System\") clr.AddReference(\"Avalonia.Controls, Version=0.10.10.0, Culture=neutral, PublicKeyToken=c8d484a7012f9a8b\") clr.AddReference(\"Avalonia.Visuals, Version=0.10.10.0, Culture=neutral, PublicKeyToken=c8d484a7012f9a8b\") clr.AddReference(\"ScheduleGenerator\") clr.AddReference(\"IronPython\") clr.AddReference(\"IronPython.Modules\")<\/code><\/pre>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e \u043c\u043e\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0432\u0441\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u043f\u0430\u043f\u043a\u0435 Traditions, \u0438 \u043a\u0430\u0436\u0434\u0430\u044f \u043f\u0430\u043f\u043a\u0430 \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435, \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043b\u0430\u0433\u0438\u043d. \u0412 \u043f\u0430\u043f\u043a\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0434\u0432\u0430 \u0444\u0430\u0439\u043b\u0430:<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044d\u0442\u043e markup.stack(\u0422\u043e \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u044e \u0441\u0442\u0430\u0442\u044c\u044e)<\/p>\n<pre><code class=\"bash\">\/text[Style=h1] \u0414\u0430\u043d\u043d\u0430\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044f \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u043d\u0430\u044f! \/text \u0414\u0430\u043d\u043d\u0430\u044f \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044f \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0430 \u0432 \u0441\u0430\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443. \u0422\u043e \u0435\u0441\u0442\u044c, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u044d\u0442\u0443 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044e, \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043d\u0438 \u043a \u043a\u0430\u043a\u0438\u043c \u044d\u0444\u0444\u0435\u043a\u0442\u0430\u043c. \/text[Name=path] \u041f\u0443\u0442\u044c \u0434\u043e \u044d\u0442\u043e\u0439 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438 : \/text[Style=h2] \u041d\u0430 \u0432\u0430\u0448 \u0432\u043e\u043f\u0440\u043e\u0441 \"\u0430 \u0437\u0430\u0447\u0435\u043c \u0437\u0434\u0435\u0441\u044c \u044d\u0442\u043e?\" \u0423 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0434\u0432\u0430 \u043e\u0442\u0432\u0435\u0442\u0430: \/text      1) \u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u043c\u0435\u043d, \u0438 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0441\u0430\u043c\u0438\u0445 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0439, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u0430\u043a \u0438\u0445 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c. \/text      2) \u0410\u0432\u0442\u043e\u0440\u0443 \u043b\u0435\u043d\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u0438\u0437\u0437\u0430\u0439\u043d \u044d\u043a\u0440\u0430\u043d\u0430, \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \/text[Style=h2; Name=foo] \u041a\u0441\u0442\u0430\u0442\u0438 \u043e\u0431 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043d\u0430\u0436\u043c\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0447\u0442\u043e \u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u044c \u0422\u0440\u0430\u0434\u0438\u0446\u0438\u0438! \/btn[Name=open_doc] \u041d\u0430\u0436\u043c\u0438 \u0421\u044e\u0434\u0430!<\/code><\/pre>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0436\u0435 &#8212; main.py :<\/p>\n<pre><code class=\"python\">from references import *  from Avalonia import * from Avalonia.Controls import *  from System import * from System.IO import * from System.Diagnostics import *  __name__ = \"\u0421\u0432\u043e\u0431\u043e\u0434\u0430 \u0413\u0440\u0430\u0444\u0438\u043a\u0430!\" __description__ = \"\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0447\u0438\u0442\u043b\u0435\u044f\u043c \u0432\u044b\u0431\u0435\u0440\u0430\u0442\u044c \u043f\u0430\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043c \u043d\u0435 \u0443\u0434\u043e\u0431\u043d\u0430.\" full_path = Path.GetFullPath(__file__)  def observe_foo(element, viewModel):     element.Margin = Thickness(0, 30, 0, 30)  def observe_path(element, viewModel):     element.Text += Path.GetDirectoryName(full_path)   def observe_open_doc(element, viewModel):     element.Click += lambda x,y : click_open_doc()   def click_open_doc():     webbrowser.open(\"https:\/\/github.com\/2Xpro-pop\/ScheduleGenerator\/tree\/master<\/code><\/pre>\n<p>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e name \u0443 \u0442\u0435\u0433\u043e\u0432 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437 python \u043a\u043e\u0434\u0430, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e observe_name, \u0433\u0434\u0435 \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u044d\u0442\u043e \u0443\u0436\u0435 &#171;\u0433\u043e\u0442\u043e\u0432\u044b\u0439&#187; \u044d\u043b\u0435\u043c\u0435\u043d\u0442 UI. \u0422\u043e \u0435\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435 \u043d\u0430\u0448 markup, \u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 Avolonia (GUI \u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a).<\/p>\n<p>\u0410 \u0432\u043e\u0442 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/3ab\/17c\/3de\/3ab17c3de28a8e4c0d5924a80fb82b7f.jpg\" width=\"1009\" height=\"486\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/3ab\/17c\/3de\/3ab17c3de28a8e4c0d5924a80fb82b7f.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/722\/9a6\/194\/7229a6194dfbdd02d4d9c4b39e9b51e1.jpg\" width=\"1009\" height=\"486\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/722\/9a6\/194\/7229a6194dfbdd02d4d9c4b39e9b51e1.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443: <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/ecc\/e2c\/a89\/ecce2ca892bb38d8e90c0f059382f8c2.jpg\" width=\"1009\" height=\"486\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ecc\/e2c\/a89\/ecce2ca892bb38d8e90c0f059382f8c2.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c IronPython, \u0430 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a xml, yaml, json, \u043d\u0443 \u0438\u043b\u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c XAML.<\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u0431\u044b\u043b\u0430 \u043b\u0438\u0448\u044c \u043c\u043e\u044f \u043a\u0443\u0440\u0441\u043e\u0432\u0430\u044f \u0438 \u0443 \u043c\u0435\u043d\u044f \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u0430\u0441\u0442\u044c \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u042f\u041f \u0438\u043b\u0438 \u044f\u0437\u044b\u043a\u0438 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438. \u0427\u0442\u043e \u0436 \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u044f \u043c\u043e\u043b\u043e\u0434\u043e\u0439, \u0438 \u0443 \u043c\u0435\u043d\u044f \u043a\u0440\u043e\u0432\u044c \u043a\u0438\u043f\u0438\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/655017\/\"> https:\/\/habr.com\/ru\/post\/655017\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption>Splash \u044d\u043a\u0440\u0430\u043d \u043c\u043e\u0435\u0439 \u043a\u0443\u0440\u0441\u043e\u0432\u043e\u0439<\/figcaption><\/figure>\n<p>\u0411\u043b\u0438\u0436\u0435 \u043a \u0434\u0435\u043b\u0443, \u0433\u043e\u0441\u043f\u043e\u0434\u0430: \u0443\u0437\u043d\u0430\u0432 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043e\u0439 \u0438\u043d\u0441\u0442\u0438\u0442\u0443\u0442 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u043a\u043e\u043d\u043a\u0443\u0440\u0441 \u043d\u0430 \u043b\u0443\u0447\u0448\u0438\u0435 \u043a\u0443\u0440\u0441\u043e\u0432\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0440\u0435\u0434\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0443\u0440\u0441\u0430, \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0437\u0430\u0439\u043c\u0443 \u043f\u0435\u0440\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e. \u041c\u043e\u0438 \u0441\u0430\u043c\u044b\u0435 \u043a\u0440\u0443\u0442\u044b\u0435 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 React, \u043a\u0442\u043e-\u0442\u043e Django, \u0430 \u043a\u0442\u043e-\u0442\u043e Tkinter. <\/p>\n<p>\u0412\u0441\u0435\u043c \u043d\u0430\u043c \u0434\u0430\u043b\u0438 \u0440\u0430\u0437\u043d\u044b\u0435 \u0442\u0435\u043c\u044b. \u0412 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u043c\u043e\u0438\u043c \u043e\u0434\u043d\u043e\u0433\u0440\u0443\u043f\u043f\u043d\u0438\u043a\u0430\u043c \u0434\u0430\u043b\u0438 \u0447\u0435\u0442\u043a\u043e\u0435 \u0422\u0417 \u0432 \u0432\u0438\u0434\u0435 word, \u0442\u043e \u043c\u043d\u0435 \u0434\u0430\u043b\u0438 \u043f\u0430\u0440\u0443 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439:<\/p>\n<blockquote>\n<p>&#171;<em>\u0421\u043e\u0437\u0434\u0430\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0439, \u0441 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:  \u044f \u043d\u0435 \u043c\u043e\u0433\u0443 \u043f\u0440\u0435\u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e \u0441\u0443\u0431\u0431\u043e\u0442\u0430\u043c, \u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043e \u043e\u0431\u0435\u0434\u0430.<\/em>&#187; <\/p>\n<\/blockquote>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d, \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0442\u043e\u0436\u0435. \u041d\u043e \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0447\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u0430\u043b\u043e, \u0438 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u043f\u0440\u0438\u0448\u043b\u0430 \u043c\u044b\u0441\u043b\u044c : <\/p>\n<blockquote>\n<p>&#171;\u042f \u0441\u043e\u0437\u0434\u0430\u043c \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a <s>\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/s> \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438, \u0441 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u0435\u0439 \u0438 \u043f\u0430\u0439\u0442\u043e\u043d\u043e\u043c!&#187;<\/p>\n<\/blockquote>\n<h2>\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441<\/h2>\n<p>\u0414\u0430, \u044f \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u044e \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434, \u0438 \u043c\u043d\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e, \u0432\u0435\u0434\u044c \u044f \u043f\u043e\u043a\u0430 \u0443\u0447\u0443\u0441\u044c. \u041d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e-\u0442\u0430\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441, \u0438 \u044f \u0435\u0433\u043e \u043f\u043e\u0437\u0430\u0438\u043c\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0443 \u043a\u043e\u043c\u0430\u043d\u0434 \u043c\u0430\u0439\u043d\u043a\u0440\u0430\u0444\u0442\u0430:<\/p>\n<pre><code class=\"cs\">\/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430 \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/code><\/pre>\n<p>\u041d\u043e \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b\u043e \u043c\u0430\u043b\u043e, \u0442\u0430\u043a \u0447\u0442\u043e \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441:<\/p>\n<pre><code>\/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430[\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04301=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04351;\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04302=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04352;....] \u043a\u043e\u043d\u0442\u0435\u043d\u0442<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0448\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0432\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u0435, \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u0447\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0435\u0433\u0438 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430.<\/p>\n<pre><code>\/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430 \/\u0438\u043c\u044f_\u0442\u0435\u0433\u0430[\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04301=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04351;\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u04302=\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u04352;....]<\/code><\/pre>\n<p>\u0418 \u0438\u043c\u044f \u044d\u0442\u043e\u043c\u0443 \u044f\u0437\u044b\u043a\u0443 &#8212; StackMarkup. \u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u0432 StackLayout \u0438 \u0442\u0430\u043a \u0436\u0435, \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c <strong><em>ToLower() <\/em><\/strong>\u0434\u043b\u044f \u0441\u0442\u0440\u043e\u043a, \u0447\u0442\u043e \u0431\u044b \u0440\u0435\u0433\u0438\u0441\u0442\u0440 \u043d\u0435 \u0438\u043c\u0435\u043b \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h2>\n<p>\u0423 \u043c\u0435\u043d\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u043b\u0430\u043d\u044b \u043d\u0430 \u044d\u0442\u043e\u0442 \u044f\u0437\u044b\u043a, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0430\u043c\u044b\u0439 \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 &#8212; \u044d\u0442\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/p>\n<pre><code class=\"cs\">public class MarkupConfiguration {         public char? BeforeCharacter { get; set; } = '\/';         public bool CustomPropertyParser { get; set; } }<\/code><\/pre>\n<p>\u0414\u0430, \u0442\u0443\u0442 \u043d\u0435 \u0433\u0443\u0441\u0442\u043e, \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c &#8212; \u044d\u0442\u043e \u043b\u0438\u0448\u044c \u0437\u0430\u0434\u0435\u043b \u043d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435.<\/p>\n<p>\u0412\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442: \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b (\u043d\u0443 \u043a\u0440\u043e\u043c\u0435 object \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435). \u041f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0430\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0434\u0432\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430:<\/p>\n<pre><code class=\"cs\">\/\/\/&lt;summary> \/\/\/ \u0414\u0430\u0435\u0442 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c(\u0438\u043b\u0438 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b) \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u043b\u0438 \u0434\u043b\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \/\/\/&lt;\/summary> [AttributeUsage(AttributeTargets.Property |                  AttributeTargets.Class |                  AttributeTargets.Struct)] public class MarkupAliasesAttribute: Attribute  {     \/\/\u0415\u0441\u043b\u0438 \u044f \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0441\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0442\u043e \u044f \u043f\u043e\u043c\u0435\u0447\u0430\u044e \u0435\u0435 \u043a\u0430\u043a readonly     \/\/\u0415\u0441\u043b\u0438 \u044f \u043d\u0435 \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0441\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u0442\u043e \u0435\u0435 \u0442\u0438\u043f \u0432\u0441\u0435\u0433\u0434\u0430 IReadOnly     public readonly IReadOnlyList&lt;string> aliases;     public MarkupAliasesAttribute(params string[] aliases)     {         var list = new List&lt;string>();         foreach(var alias in aliases)\/\/ \u041a \u0447\u0435\u0440\u0442\u0443 Linq \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c foreach!         {             list.Add(alias.Trim().ToLower());         }         this.aliases = list.AsReadOnly();     } }  \/\/\/&lt;summary> \/\/\/ \u0418\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0442\u043e\u0447\u043d\u0435\u0435 \u0435\u0433\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u0437\u0430\u0434\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 Markup \/\/\/&lt;\/summary> [AttributeUsage(AttributeTargets.Property)] public class MarkupIgnoreAttribute: Attribute {}<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435, \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u044b \u043f\u043e\u043b\u043e\u043c\u0430\u044e\u0442 \u0432\u0435\u0441\u044c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441. \u041d\u043e \u044d\u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u043d\u0435 \u0437\u0434\u0435\u0441\u044c, \u0442\u0430\u043a \u043a\u0430\u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0438\u043c\u0435\u044e\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 &#171;\u043b\u0435\u043d\u0438\u0432\u043e\u0439 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438&#187;. \u0414\u0430\u043b\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f :<\/p>\n<pre><code class=\"cs\">\/\/\/&lt;param> \/\/\/ \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \/\/\/&lt;param> public class AliasException: Exception {     \/\/ \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435     \/\/ \u0440\u0435\u0433\u044d\u043a\u0441, \u043c\u044b \u043f\u0440\u043e\u043f\u0438\u0448\u0435\u043c \u0435\u0433\u043e \u043a\u0430\u043a static readonly \u0447\u0442\u043e \u0440\u0430\u0432\u043d\u043e\u0441\u0438\u043b\u044c\u043d\u043e \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0435     \/\/ \u0442\u0430\u043a \u0436\u0435 \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0443\u043a\u0430\u0436\u0435\u043c RegexOptions.Compiled, \u0442\u0430\u043a \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c      \/\/ \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u043e\u0434\u043d\u0430\u043a\u0430 \u0435\u0433\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0439,      \/\/ \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0447\u0430\u0441\u0442\u043e \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c     private static readonly Regex _isLetterOnly = new Regex(@\"^[a-zA-Z]+$\",                                                             RegexOptions.Compiled);     \/\/\/&lt;param>     \/\/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438\u043c\u044f \u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u044c, \u0435\u0441\u043b\u0438 \u0438\u043c\u044f \u043d\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435     \/\/\/&lt;\/param>     public static void CheckNaming(string alias, MarkupConfiguration configuration)     {         if(alias.Contains(' '))         {             throw new AliasException($\"\u0418\u043c\u044f {alias} \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0431\u0435\u043b\u044b!\");         }         if(!_isLetterOnly.IsMatch(alias))         {             throw new AliasException($\"\u0418\u043c\u044f {alias} \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b!\");         }     }     public AliasException(string message):base(message){} }  \/\/\/&lt;param> \/\/\/ \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 \/\/\/&lt;param> public class SyntaxException: Exception {     public static void CheckIsEmptyName(string substring)     {         if(string.IsNullOrWhiteSpace(substring))         {             throw new SyntaxException(\"\u0418\u043c\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c!\");         }     }     public SyntaxException(string message): base(message) {} }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u0435\u043d \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443( \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0444\u0430\u0439\u043b\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043e\u0434 StackMarkup). \u042f \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b Antrl, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b \u0435\u0433\u043e \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043e\u0449\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u041d\u0435 \u043f\u0443\u0433\u0430\u0439\u0442\u0435\u0441\u044c \u0442\u0430\u043a\u043e\u0433\u043e &#171;\u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0433\u043e&#187; \u043a\u043e\u0434\u0430, \u0443\u043c\u0435\u043b \u0431\u044b \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c RegEx \u043e\u043d \u0431\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u0431\u044b \u043a\u043e\u0440\u043e\u0447\u0435&#8230;.<\/p>\n<details class=\"spoiler\">\n<summary>MarkupParsedRow.cs<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public class MarkupParsedRow {     \/\/ \u0414\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0433\u044d\u043a\u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u043d \u043b\u0438 \u0442\u0435\u0433 \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c(\u0438) \u0438\u043b\u0438 \u0431\u0435\u0437     private static readonly Regex _elementWithProperties = new Regex(         @\"[a-zA-Z]+\\[[^\\]]*\\](\\.[^\\]]*\\])?\",          RegexOptions.Compiled     );      public MarkupParsedRow(string row, MarkupConfiguration configuration)     {         if(configuration.BeforeCharacter != null)         {             SetCountBeforeCharacter(row, configuration);         }                  \/\/ \u0423\u0434\u0430\u043b\u044f\u0435\u043c \u0432\u0441\u0435 \u043f\u0435\u0440\u0432\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b (\u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \"\/\")         row = row.Remove(0, CountBeforeCharacter);                \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u0435\u0441\u043b\u0438 i=-1 \u0437\u043d\u0430\u0447\u0438\u0442 \u044d\u0435\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0435\u0437 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430         int i = 0;         while (row.IndexOf(' ', i) &lt; row.IndexOf(']'))         {             i = row.IndexOf(' ', i+1);             if (i == -1)             {                 break;             }         }          if (i!= -1) \/\/ \u0435\u0441\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442         {             \/\/ defination \u0442\u0430 \u0436\u0435 \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u043e \u0441 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430             var defination = row.Substring(0, row.IndexOf(' ', i));                          SyntaxException.CheckIsEmptyName(defination);             \/\/ \u0435\u0441\u043b\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0442\u043e \u0443\u0441\u0442\u043e\u043d\u0430\u0432\u043b\u0438\u0432\u0435\u043c \u0438 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u0438 \u0438\u043c\u044f,              \/\/ \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430             if(_elementWithProperties.IsMatch(defination))             {                 SetNameAndProperty(defination, configuration);                 Content = row.Replace($\"{MarkupElementName}[{PropertiesString}] \", \"\");             }             else             {                 \/\/ \u0435\u0441\u043b\u0438 \u0436\u0435 \u043d\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442 defination \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u044f                 MarkupElementName = defination;                 AliasException.CheckNaming(MarkupElementName, configuration);                 Content = row.Replace($\"{MarkupElementName} \", \"\");             }         }         \/\/ \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430, \u043d\u043e \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430         else if (_elementWithProperties.IsMatch(row))          {             SetNameAndProperty(row, configuration);         }         \/\/ \u0435\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u043c\u044f         else          {             SyntaxException.CheckIsEmptyName(row);             MarkupElementName = row;         }          MarkupElementName = MarkupElementName.ToLower().Trim();     }     \/\/ \u0417\u0430\u0434\u0435\u043b \u043d\u0430 \u0431\u0443\u0434\u0443\u0449\u0435\u0435     public int CountBeforeCharacter { get; private set; } = 0;      \/\/ \u0418\u043c\u044f \u0441\u0430\u043c\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430     public string MarkupElementName { get; private set; }      \/\/ \u0421\u0442\u0440\u043e\u043a\u0430 \u0441\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0435\u0441\u0442\u044c     public string? PropertiesString { get; private set; }     \/\/ \u041a\u043e\u043d\u0442\u0435\u043d\u0442, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0441\u0442\u044c     public string? Content { get; private set; }      private void SetCountBeforeCharacter(string row, MarkupConfiguration configuration)     {         foreach(var character in row)         {             if(character == configuration.BeforeCharacter)             {                 CountBeforeCharacter += 1;                 continue;             }             break;         }     }     \/\/\/ \u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0418\u043c\u044f \u0438 \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430      private void SetNameAndProperty(string defination, MarkupConfiguration configuration)     {         MarkupElementName = defination.Substring(0, defination.IndexOf('['));         PropertiesString = defination.Substring(             defination.IndexOf('[') + 1,             defination.IndexOf(']') - defination.IndexOf('[') -1         );         AliasException.CheckNaming(MarkupElementName, configuration);     }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0433\u0447\u0435. \u041d\u0443\u0436\u0435\u043d \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0437 MarkupParsedRow \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442. \u0412\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u0443\u0447\u0435\u0441\u0442\u044c, \u0447\u0442\u043e net 5 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435 \u043d\u0430\u0434\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u043a\u0435\u0442\u044b. <\/p>\n<p>\u041e\u0434\u043d\u043e \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 &#8212; \u044d\u0442\u043e <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.componentmodel.typedescriptor\" rel=\"noopener noreferrer nofollow\"><strong>TypeDescriptor<\/strong><\/a>, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c <a href=\"https:\/\/www.hanselman.com\/blog\/typeconverters-theres-not-enough-typedescriptergetconverter-in-the-world\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>. <\/p>\n<p>\u0410 \u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043c\u043d\u0435 \u0434\u0430\u0436\u0435 \u043d\u0435 \u043d\u0430\u0434\u043e : \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u0437\u0430 \u043c\u0435\u043d\u044f <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.data.common.dbconnectionstringbuilder\" rel=\"noopener noreferrer nofollow\"><strong>DbConnectionStringBuilder<\/strong><\/a><\/p>\n<p>\u042d\u0442\u043e \u0435\u0449\u0435 \u043d\u0435 \u0432\u0441\u0435. \u0422\u0430\u043a \u0436\u0435 \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/api\/system.activator\" rel=\"noopener noreferrer nofollow\"><strong>Activator<\/strong><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0442\u0438\u043f\u0430.<\/p>\n<pre><code class=\"cs\">public class MarkupElementDefination {         \/\/ \u0422\u0438\u043f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         private readonly Type _elementType;         \/\/ \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430         private readonly Dictionary&lt;string, PropertyInfo> _properties = new Dictionary&lt;string, PropertyInfo>();         \/\/ \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430         private readonly MarkupConfiguration _configuration;         \/\/ \u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442         private readonly PropertyInfo _content = null;                  \/\/ \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442         public MarkupElementDefination(Type elementType, MarkupConfiguration configuration)         {             _elementType = elementType;             _configuration = configuration;             \/\/ \u0427\u0438\u0442\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430             foreach(var property in elementType.GetProperties())             {                 \/\/ \u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 MarkupIgnore, \u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e                 if(property.GetCustomAttribute&lt;MarkupIgnoreAttribute>() != null)                 {                     continue;                 }                 \/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430                 foreach(var attribute in property.GetCustomAttributes())                 {<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-330481","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330481","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=330481"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330481\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330481"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330481"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330481"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}