{"id":489635,"date":"2026-08-04T05:43:55","date_gmt":"2026-08-04T05:43:55","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=489635"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=489635","title":{"rendered":"\u0421\u043e\u0437\u0434\u0430\u0451\u043c DSL \u043d\u0430 C#: \u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u043e\u0448\u0451\u043b(\u043e\u043f\u044f\u0442\u044c) \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043c\u0435\u0441\u044f\u0446 \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 \u0438 \u043d\u0430\u0443\u0447\u0438\u043b\u0438 Akbura \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<ol>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/970332\/\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/1042432\/\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u043f\u0430\u0440\u0441\u0435\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/1046103\/\" rel=\"noopener noreferrer nofollow\">\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0431\u043b\u0435\u043d\u0434\u0435\u0440<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/1058512\/\" rel=\"noopener noreferrer nofollow\">\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443<\/a><\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c Language Server Protocol \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432 Visual Studio<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434<\/p>\n<\/li>\n<\/ol>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/64\/eb\/a7\/64eba73444e67d3ababc73aab595b07c.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/64\/eb\/a7\/64eba73444e67d3ababc73aab595b07c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/64\/eb\/a7\/64eba73444e67d3ababc73aab595b07c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<blockquote>\n<p>\u0412\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u0434\u0430 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430, \u043d\u043e \u044d\u0442\u043e \u0442\u043e\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0435\u0439\u0440\u043e\u0441\u043b\u043e\u043f, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0430\u043b \u0418\u0418 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0438\u043c\u0435\u044f \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0438 Api. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043b\u0430\u0447\u0435\u0432\u043d\u044b\u0439, 33 \u0444\u0430\u0439\u043b\u0430 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u044c\u0441\u044f 2 \u043c\u0438\u043d\u0443\u0442\u044b \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u0441\u0431\u043e\u0440\u043a\u0438, \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0443 \u043d\u0430 \u0442\u043e \u044d\u0442\u043e \u0438 <a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/tree\/master\/Akbura.Furioso\" rel=\"noopener noreferrer nofollow\">\u0444\u0443\u0440\u0438\u043e\u0441\u0430<\/a><\/p>\n<\/blockquote>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0443\u0442\u043e\u0447\u043d\u044e: \u043f\u043e\u0434 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u043e\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0438\u043c\u0435\u044e \u0432 \u0432\u0438\u0434\u0443 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442. \u041f\u0430\u0440\u0441\u0435\u0440 \u0438 binder \u0443\u043c\u0435\u044e\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c diagnostics, \u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0434\u043e LSP.<\/p>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0440\u0443\u0433\u0430\u044f. \u042f \u0445\u043e\u0447\u0443 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b Akbura \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043e\u043d\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u0438\u0435 \u0443 \u043d\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0438\u0445 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0447\u0435\u043c\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e\u0434\u0440\u044f\u0434;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 <code>.akbura<\/code>-\u0444\u0430\u0439\u043b\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0417\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p>Akbura \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 Avalonia, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c visual tree \u0438 logical tree.<\/p>\n<p>\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c Avalonia Developer Tools \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0441\u0451 \u0442\u0430\u043c. \u041d\u043e \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043e\u0432 Avalonia \u0438 \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 Akbura \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442:<\/p>\n<pre><code class=\"cs\">&lt;CounterPage&gt;    &lt;StackPanel&gt;        &lt;TextBlock Text={count} \/&gt;        &lt;Button Click={() =&gt; count++}&gt;            Increment        &lt;\/Button&gt;    &lt;\/StackPanel&gt;&lt;\/CounterPage&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f Avalonia \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 <code>StackPanel<\/code>, <code>TextBlock<\/code>, <code>Button<\/code>, \u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0441\u0442\u0438\u043b\u0438 \u0438 layout.<\/p>\n<p>\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f Akbura \u043d\u0430\u0441 \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u0430\u043c <code>CounterPage<\/code>: \u0435\u0433\u043e <code>state<\/code>, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, injected services \u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<p>\u041e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Akbura \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u043e. \u0415\u0441\u043b\u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 visual tree, \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0431\u044b\u0441\u0442\u0440\u043e \u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f.<\/p>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"cs\">public interface IComponentTree{    IComponentTree? ComponentParent { get; }    IAvaloniaReadOnlyList&lt;IComponentTree&gt; ComponentChildren { get; }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura\/ComponentTree\/IComponentTree.cs\" rel=\"noopener noreferrer nofollow\"><code>IComponentTree.cs<\/code><\/a>.<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 <code>AkburaControl<\/code> \u0445\u0440\u0430\u043d\u0438\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<pre><code class=\"cs\">private readonly AvaloniaList&lt;IComponentTree&gt; _componentChildren = [];private IComponentTree? _componentParent;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u043a visual tree, \u043e\u043d \u0438\u0449\u0435\u0442 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>IComponentTree<\/code>:<\/p>\n<pre><code class=\"cs\">protected override void OnAttachedToVisualTree(    VisualTreeAttachmentEventArgs e){    base.OnAttachedToVisualTree(e);    SetComponentParent(FindComponentParent());    AkburaComponentRegistry.Attach(this);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0438 \u043e\u0442\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u044f\u0437\u044c \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"cs\">protected override void OnDetachedFromVisualTree(    VisualTreeAttachmentEventArgs e){    base.OnDetachedFromVisualTree(e);    _useHooks.StopForDetach();    SetComponentParent(null);    AkburaComponentRegistry.Detach(this);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0438\u0441\u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043f\u043e\u043a\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439:<\/p>\n<pre><code class=\"cs\">private IComponentTree? FindComponentParent(){    for (var parent = this.GetVisualParent();         parent != null;         parent = parent.GetVisualParent())    {        if (parent is IComponentTree componentParent)        {            return componentParent;        }    }    return null;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u043f\u043e visual tree, \u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b Akbura. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435, \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e:<\/p>\n<pre><code>App\u251c\u2500\u2500 Navigation\u251c\u2500\u2500 Sidebar\u2514\u2500\u2500 Router    \u2514\u2500\u2500 CounterPage        \u2514\u2500\u2500 CounterButton<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0420\u0435\u0435\u0441\u0442\u0440 \u0436\u0438\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p>\u041e\u0434\u043d\u043e\u0433\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f <code>parent =&gt; children<\/code> \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0443 \u0435\u0449\u0451 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u0443\u0434\u0430-\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 <code>AkburaComponentRegistry<\/code>.<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u043e\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"cs\">internal static class AkburaComponentRegistry{    private static readonly object s_gate = new();    private static readonly List&lt;WeakReference&lt;AkburaControl&gt;&gt;        s_components = [];    internal static event EventHandler? Changed;    internal static void Attach(AkburaControl component)    {        lock (s_gate)        {            s_components.Add(                new WeakReference&lt;AkburaControl&gt;(component));        }        Changed?.Invoke(null, EventArgs.Empty);    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e, \u0447\u0442\u043e \u0440\u0435\u0435\u0441\u0442\u0440 \u0445\u0440\u0430\u043d\u0438\u0442 \u043d\u0435 \u0441\u0430\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0430 <code>WeakReference&lt;AkburaControl&gt;<\/code>.<\/p>\n<p>\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u043c \u043c\u0443\u0441\u043e\u0440\u0430. \u0418\u043d\u0430\u0447\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u0439\u0442\u0438 \u0443\u0442\u0435\u0447\u043a\u0443 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u0430\u043c\u0430 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0443\u0442\u0435\u0447\u043a\u0443 \u043f\u0430\u043c\u044f\u0442\u0438, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u0440\u043e\u043d\u0438\u0447\u043d\u043e.<\/p>\n<p>\u041f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438 \u0440\u0435\u0435\u0441\u0442\u0440 \u0437\u0430\u043e\u0434\u043d\u043e \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0443\u0436\u0435 \u043c\u0451\u0440\u0442\u0432\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438:<\/p>\n<pre><code class=\"cs\">internal static ImmutableArray&lt;AkburaControl&gt;    GetAttachedComponents(){    lock (s_gate)    {        var builder =            ImmutableArray.CreateBuilder&lt;AkburaControl&gt;();        for (var index = 0;             index &lt; s_components.Count;)        {            if (s_components[index]                .TryGetTarget(out var component))            {                builder.Add(component);                index++;            }            else            {                s_components.RemoveAt(index);            }        }        return builder.ToImmutable();    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0423 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <code>Changed<\/code>. \u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0433\u043e \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0434\u0435\u0440\u0435\u0432\u043e, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p>\u041f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura\/ComponentTree\/AkburaComponentRegistry.cs\" rel=\"noopener noreferrer nofollow\"><code>AkburaComponentRegistry.cs<\/code><\/a>.<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440<\/h3>\n<p>\u0421\u0430\u043c \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u044f \u0432\u044b\u043d\u0435\u0441 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 <code>Akbura.Diagnostics<\/code>.<\/p>\n<p>\u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u0430\u043d\u0435\u043b\u044c \u0432 Release-\u0441\u0431\u043e\u0440\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Debug:<\/p>\n<pre><code class=\"cs\">using Akbura.Diagnostics;using Avalonia;public partial class App : Application{    public override void Initialize()    {        AvaloniaXamlLoader.Load(this);#if DEBUG        this.AttachAkburaDevTools();#endif    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043a\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e <code>F12<\/code>.<\/p>\n<p>\u0413\u043e\u0440\u044f\u0447\u0443\u044e \u043a\u043b\u0430\u0432\u0438\u0448\u0443 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c:<\/p>\n<pre><code class=\"cs\">#if DEBUGthis.AttachAkburaDevTools(options =&gt;{    options.ToggleGesture = new KeyGesture(        Key.F12,        KeyModifiers.Control);});#endif<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u043a\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f classic desktop application lifetime.<\/p>\n<p>\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0430\u043c\u043e \u043e\u043a\u043d\u043e \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 \u0438\u0437 \u0440\u0435\u0435\u0441\u0442\u0440\u0430:<\/p>\n<pre><code class=\"cs\">AkburaComponentRegistry.ExcludeTopLevel(this);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u0443\u0432\u0438\u0434\u0438\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 <code>DiagnosticsRoot<\/code>, \u0434\u043e\u0431\u0430\u0432\u0438\u0442 \u0435\u0433\u043e \u0432 \u0434\u0435\u0440\u0435\u0432\u043e, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u043d\u0451\u0442 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c \u0441\u0435\u0431\u044f. \u0417\u0432\u0443\u0447\u0438\u0442 \u0432\u0435\u0441\u0435\u043b\u043e, \u043d\u043e \u043f\u043e\u043b\u044c\u0437\u044b \u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e.<\/p>\n<h3>\u0421\u0442\u0440\u043e\u0438\u043c \u0434\u0435\u0440\u0435\u0432\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435<\/h3>\n<p>\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0441\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<pre><code class=\"cs\">var components =    AkburaComponentRegistry        .GetAttachedComponents()        .Where(IsApplicationComponent)        .ToArray();<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u0440\u043d\u0438. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043d\u0430\u0431\u043e\u0440\u0435:<\/p>\n<pre><code class=\"cs\">var componentSet = new HashSet&lt;AkburaControl&gt;(    components,    ReferenceEqualityComparer.Instance);var roots = components    .Where(component =&gt;        ((IComponentTree)component).ComponentParent            is not AkburaControl parent ||        !componentSet.Contains(parent))    .ToArray();<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u0437 \u043a\u043e\u0440\u043d\u0435\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b <code>TreeView<\/code>.<\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0438\u043c\u044f \u0442\u0438\u043f\u0430 \u0438 <code>Name<\/code>, \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u0434\u0430\u043d:<\/p>\n<pre><code class=\"cs\">private static string GetComponentDisplayName(    AkburaControl component){    var typeName = component.GetType().Name;    return string.IsNullOrWhiteSpace(component.Name)        ? typeName        : $\"{typeName}  #{component.Name}\";}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/6a\/5e\/33\/6a5e33e8be9a8fa8bac9c3a7e9c0ba67.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/6a\/5e\/33\/6a5e33e8be9a8fa8bac9c3a7e9c0ba67.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/6a\/5e\/33\/6a5e33e8be9a8fa8bac9c3a7e9c0ba67.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<h3>\u0427\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/h3>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0430:<\/p>\n<ul>\n<li>\n<p><code>Services<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>States<\/code>;<\/p>\n<\/li>\n<li>\n<p><code>Parameters<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e <code>AkburaControl<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<pre><code class=\"cs\">internal ImmutableArray&lt;Parameter&gt;    GetDiagnosticParameters(){    return GetParameters();}internal ImmutableArray&lt;InjectService&gt;    GetDiagnosticServices(){    return GetServices();}internal ImmutableArray&lt;State&gt;    GetDiagnosticStates(){    return GetStates();}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u0435\u0440\u0432\u0438\u0441\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e injected service \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0442\u0438\u043f, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e:<\/p>\n<pre><code class=\"cs\">_selectedComponent.PropertyChanged +=    OnSelectedPropertyChanged;foreach (var state in         _selectedComponent.GetDiagnosticStates()){    state.ValueChanged += OnSelectedStateChanged;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043e\u043a\u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f <code>state<\/code> \u0438\u043b\u0438 Avalonia property.<\/p>\n<h3>\u0418\u0437\u043c\u0435\u043d\u044f\u0435\u043c state \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430 \u043b\u0435\u0442\u0443<\/h3>\n<p>\u041f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u041c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c <code>state<\/code>, \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0435\u0441\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 <code>InputBuilder<\/code>.<\/p>\n<p>\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 builders \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442:<\/p>\n<ul>\n<li>\n<p>\u0441\u0442\u0440\u043e\u043a\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0447\u0438\u0441\u043b\u0430;<\/p>\n<\/li>\n<li>\n<p>\u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438;<\/p>\n<\/li>\n<li>\n<p>\u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>TypeConverter<\/code>, \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 <code>Parse<\/code> \u0438 <code>TryParse<\/code>, \u0430 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u2014 JSON.<\/p>\n<p>\u041f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 <code>state<\/code> \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <code>BoxedValue<\/code>:<\/p>\n<pre><code class=\"cs\">value =&gt; state.BoxedValue = value<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a Avalonia property:<\/p>\n<pre><code class=\"cs\">component.SetCurrentValue(property, value);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f read-only \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442, \u0430 \u043e\u0447\u0438\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0438 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0432 \u043d\u0435\u0451 \u043d\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439:<\/p>\n<pre><code class=\"cs\">this.AttachAkburaDevTools(options =&gt;{    options.InputBuilders.Insert(        0,        new RouteInputBuilder());});<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Builders \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 selector.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f <code>Url<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 <code>TextBox<\/code>, \u0430 <code>ComboBox<\/code> \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/9a\/87\/6e\/9a876ea5d7f999fde1f039176afb6bff.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/9a\/87\/6e\/9a876ea5d7f999fde1f039176afb6bff.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/9a\/87\/6e\/9a876ea5d7f999fde1f039176afb6bff.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/44\/0b\/80\/440b80fcf8f0960610d36bebfa656b0a.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/44\/0b\/80\/440b80fcf8f0960610d36bebfa656b0a.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/44\/0b\/80\/440b80fcf8f0960610d36bebfa656b0a.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u043a\u043d\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura.Diagnostics\/DiagnosticsRoot.cs\" rel=\"noopener noreferrer nofollow\"><code>DiagnosticsRoot.cs<\/code><\/a>.<\/p>\n<h3>\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u2014 \u044d\u0442\u043e \u0435\u0449\u0451 \u043d\u0435 \u0432\u0441\u044f \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430<\/h3>\n<p>\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441 \u00ab\u0447\u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u00bb.<\/p>\n<p>\u041d\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:<\/p>\n<ul>\n<li>\n<p>\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043d\u044f\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0441\u044f <code>Update<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0448\u043b\u043e \u0437\u0430 \u043e\u0434\u0438\u043d batch;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442 \u043b\u0438\u043c\u0438\u0442\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439;<\/p>\n<\/li>\n<li>\n<p>\u0433\u0434\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 API .NET:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.diagnostics.activitysource?view=net-10.0\" rel=\"noopener noreferrer nofollow\"><code>ActivitySource<\/code><\/a> \u0434\u043b\u044f \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043e\u043a;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/api\/system.diagnostics.metrics.meter?view=net-10.0\" rel=\"noopener noreferrer nofollow\"><code>Meter<\/code><\/a> \u0434\u043b\u044f \u043c\u0435\u0442\u0440\u0438\u043a.<\/p>\n<\/li>\n<\/ul>\n<p>\u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0435\u0449\u0451 \u0438 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e Akbura \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u043d\u0430\u0442\u044c, \u043a\u0443\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 telemetry. \u0415\u0451 \u043c\u043e\u0436\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>ActivityListener<\/code>, OpenTelemetry, <code>dotnet-counters<\/code> \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442.<\/p>\n<h3>\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443<\/h3>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e runtime-\u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430.<\/p>\n<p>\u041e\u043d\u0430 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>AppContext<\/code> switch:<\/p>\n<pre><code class=\"cs\">private const string IsEnabledSwitchName =    \"Akbura.Diagnostics.Diagnostic.IsEnabled\";private static bool InitializeIsEnabled(){    return AppContext.TryGetSwitch(               IsEnabledSwitchName,               out var isEnabled) &amp;&amp;           isEnabled;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f switch \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup Condition=\"'$(Configuration)' == 'Debug'\"&gt;    &lt;RuntimeHostConfigurationOption        Include=\"Akbura.Diagnostics.Diagnostic.IsEnabled\"        Value=\"true\" \/&gt;&lt;\/ItemGroup&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f <code>ActivitySource<\/code> \u0438 <code>Meter<\/code>:<\/p>\n<pre><code class=\"cs\">static Diagnostic(){    IsEnabled = InitializeIsEnabled();    if (!IsEnabled)    {        return;    }    InitActivitySource();    InitMetrics();}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0432 \u043e\u0431\u044b\u0447\u043d\u043e\u0439 Release-\u0441\u0431\u043e\u0440\u043a\u0435 \u043c\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u043e\u043e\u0431\u0449\u0435.<\/p>\n<h3>\u0422\u0440\u0430\u0441\u0441\u0438\u0440\u0443\u0435\u043c \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/h3>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 Akbura \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u0434\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 activity:<\/p>\n<pre><code>Akbura.Component.InitializeAkbura.Component.UpdateBatch<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437:<\/p>\n<pre><code class=\"cs\">private static void InitActivitySource(){    s_activitySource = new ActivitySource(        \"Akbura.Diagnostic.Source\");}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0439 <code>using<\/code>:<\/p>\n<pre><code class=\"cs\">protected override void OnInitialized(){    base.OnInitialized();    using var activity =        Diagnostic.StartComponentInitialization(this);    using var duration =        Diagnostic.BeginComponentInitialization(this);    try    {        InitializeAkburaComponent();    }    catch (Exception exception)    {        Diagnostic.SetActivityError(            activity,            exception);        throw;    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>ActivitySource.StartActivity()<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>null<\/code>, \u0435\u0441\u043b\u0438 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0441\u043b\u0443\u0448\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u044d\u0442\u043e\u043c\u0443 instrumentation \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u0436\u0435 \u0432 \u0447\u0430\u0441\u0442\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u043c \u043a\u043e\u0434\u0435: \u0431\u0435\u0437 listener \u043e\u0431\u044a\u0435\u043a\u0442 <code>Activity<\/code> \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f.<\/p>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f activity \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0442\u0438\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430:<\/p>\n<pre><code class=\"cs\">activity.SetTag(    \"akbura.component.type\",    GetComponentTypeName(component));<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, activity \u043f\u043e\u043c\u0435\u0447\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u0430\u044f:<\/p>\n<pre><code class=\"cs\">activity.SetStatus(    ActivityStatusCode.Error);activity.SetTag(    \"error.type\",    exception.GetType().FullName);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f update batch \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439:<\/p>\n<pre><code class=\"cs\">activity?.SetTag(    Diagnostic.Tags.UpdateCount,    updateCount);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b \u043b\u0438\u043c\u0438\u0442, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u0441\u0430\u043c \u043b\u0438\u043c\u0438\u0442.<\/p>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u0439 <code>Update<\/code>, \u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439.<\/p>\n<h3>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u0440\u0438\u043a\u0438<\/h3>\n<p>\u0414\u043b\u044f \u043c\u0435\u0442\u0440\u0438\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>System.Diagnostics.Metrics.Meter<\/code>:<\/p>\n<pre><code class=\"cs\">var meter = new Meter(    \"Akbura.Diagnostic.Meter\");<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441 \u044f \u0441\u043e\u0431\u0438\u0440\u0430\u044e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>akbura.component.initialize.durationakbura.component.update.batch.durationakbura.component.update.batch.sizeakbura.component.update.limit_exceeded.countakbura.component.attached.count<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0435\u0440\u0432\u044b\u0435 \u0434\u0432\u0435 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f histogram. \u041e\u043d\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0440\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f, \u043d\u043e \u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0420\u0430\u0437\u043c\u0435\u0440 update batch \u0442\u043e\u0436\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 histogram:<\/p>\n<pre><code class=\"cs\">histogram.Record(    updateCount,    new KeyValuePair&lt;string, object?&gt;(        Diagnostic.Tags.ComponentType,        GetComponentTypeName(component)));<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0438\u0435 \u043b\u0438\u043c\u0438\u0442\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <code>Counter&lt;long&gt;<\/code>, \u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0436\u0438\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432  \u0447\u0435\u0440\u0435\u0437 observable counter:<\/p>\n<pre><code class=\"cs\">meter.CreateObservableUpDownCounter(    Meters.AttachedComponentCountName,    AkburaComponentRegistry        .GetAttachedComponentCount,    Meters.ComponentUnit,    Meters.AttachedComponentCountDescription);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 <code>ref struct<\/code>:<\/p>\n<pre><code class=\"cs\">internal readonly ref struct    HistogramReportDisposable{    private readonly long _timestamp;    public HistogramReportDisposable(...)    {        _timestamp = Stopwatch.GetTimestamp();    }    public void Dispose()    {        var elapsed =            Stopwatch.GetElapsedTime(_timestamp)                .TotalMilliseconds;        \/\/ histogram.Record(...)    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f, \u0432\u043a\u043b\u044e\u0447\u0451\u043d \u043b\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442:<\/p>\n<pre><code class=\"cs\">if (histogram is not { Enabled: true }){    return default;}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 listener \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, Akbura \u0434\u0430\u0436\u0435 \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 <code>Stopwatch.GetTimestamp()<\/code>.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 <code>dotnet-counters<\/code>:<\/p>\n<pre><code>dnx dotnet-counters monitor --process-id &lt;PID&gt; --counters Akbura.Diagnostic.Meter<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043f\u043e\u043a\u0430\u0436\u0435\u0442 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u0440\u0435\u043c\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439, \u0440\u0430\u0437\u043c\u0435\u0440 batch \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura\/Diagnostics\/Diagnostic.Activities.cs\" rel=\"noopener noreferrer nofollow\"><code>Diagnostic.Activities.cs<\/code><\/a>;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura\/Diagnostics\/Diagnostic.Metrics.cs\" rel=\"noopener noreferrer nofollow\"><code>Diagnostic.Metrics.cs<\/code><\/a>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u0435\u0441\u0442\u0438 \u0432 .akbura, \u0430 \u043d\u0435 \u0432 .g.cs<\/h3>\n<p>\u041e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0430 \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430.<\/p>\n<p>Akbura \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 C#. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e source mapping \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code>System.DivideByZeroException   at Counter.Update()   in Akbura.Component.Counter.akbura.31ac4f.g.cs:line 428<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u0438\u0441\u0430\u043b \u0441\u0442\u0440\u043e\u043a\u0443 428 \u044d\u0442\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043e\u043d, \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0434\u0430\u0436\u0435 \u043d\u0435 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u043b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b.<\/p>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b debugger \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 <code>.akbura<\/code>:<\/p>\n<pre><code>System.DivideByZeroException   at Counter.Update()   in C:\\Project\\Counter.akbura:line 14<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e C# \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0443 <a href=\"https:\/\/learn.microsoft.com\/en-us\/dotnet\/csharp\/language-reference\/proposals\/csharp-10.0\/enhanced-line-directives\" rel=\"noopener noreferrer nofollow\"><code>#line<\/code><\/a>.<\/p>\n<p>\u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u043e\u043c\u0435\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430:<\/p>\n<pre><code class=\"cs\">#line 14 \"Counter.akbura\"var result = 10 \/ divisor;#line default<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u043e Akbura \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u0437 DSL \u043c\u043e\u0436\u0435\u0442 \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u043b\u0438\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430:<\/p>\n<pre><code class=\"cs\">((AvaloniaObject)__element4).SetValue(    TextBlock.TextProperty,    items[index].Name);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0443\u044e \u0444\u043e\u0440\u043c\u0443 <code>#line<\/code>, \u043f\u043e\u044f\u0432\u0438\u0432\u0448\u0443\u044e\u0441\u044f \u0432 C# 10:<\/p>\n<pre><code class=\"cs\">#line (14,19)-(14,36) 78 \"C:\\Project\\Counter.akbura\"((AvaloniaObject)__element4).SetValue(TextBlock.TextProperty, items[index].Name);#line default<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c:<\/p>\n<pre><code>(14,19) \u2014 \u043d\u0430\u0447\u0430\u043b\u043e span \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c .akbura;(14,36) \u2014 \u043a\u043e\u043d\u0435\u0446 span;78      \u2014 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438;path    \u2014 \u043f\u0443\u0442\u044c \u043a \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0421\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e <code>items[index].Name<\/code> \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. \u041f\u0435\u0440\u0435\u0434 \u043d\u0438\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0432\u044b\u0437\u043e\u0432 <code>SetValue<\/code>, target \u0438 property.<\/p>\n<h3>\u0421\u0442\u0440\u043e\u0438\u043c source map<\/h3>\n<p>\u0414\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>TextSpan<\/code> \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u043a\u043e\u043b\u043e\u043d\u043a\u0443 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b <code>ComponentGenerationSourceMap<\/code>.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f:<\/p>\n<pre><code class=\"cs\">lineSpan = _syntaxTree.Text.Lines    .GetLinePositionSpan(syntax.Span);<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0435\u0440\u0435\u0434 \u044d\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u043b\u0438 \u0443\u0437\u0435\u043b \u043d\u0443\u0436\u043d\u043e\u043c\u0443 syntax tree;<\/p>\n<\/li>\n<li>\n<p>\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0436\u043d\u043e \u043b\u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043f\u0443\u0442\u044c \u0432 <code>#line<\/code>;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 span \u043f\u0443\u0441\u0442\u044b\u043c;<\/p>\n<\/li>\n<li>\n<p>\u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043b\u0438 span \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 mapping \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f, \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 C# \u0431\u0435\u0437 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u044b.<\/p>\n<p>\u0421\u0430\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u0434\u0438\u043d \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"cs\">private void AppendLineDirective(    StringBuilder source,    int indentation,    AkburaSyntax syntax,    string statement,    int valueOffset){    if (_sourceMap.TryGetLineDirective(            syntax,            out var span,            out var path))    {        var generatedOffset =            indentation * 4 +            Math.Max(0, valueOffset);        \/\/ #line (...)        \/\/ statement        \/\/ #line default        return;    }    AppendIndentedLine(        source,        indentation,        statement);}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"cs\">#line default<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418\u043d\u0430\u0447\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0442\u043e\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e <code>.akbura<\/code>-\u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c mapping \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u0440\u0430\u0437\u0443 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445:<\/p>\n<ul>\n<li>\n<p>\u043e\u0448\u0438\u0431\u043a\u0438 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 DSL;<\/p>\n<\/li>\n<li>\n<p>debugger \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c breakpoint \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435;<\/p>\n<\/li>\n<li>\n<p>sequence points \u0432 PDB \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0441 <code>.akbura<\/code>;<\/p>\n<\/li>\n<li>\n<p>stack trace \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0438 \u0441\u0442\u0440\u043e\u043a\u0443.<\/p>\n<\/li>\n<\/ul>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/51\/7f\/10\/517f10577e1ed9affa782650dd7c9f84.png\" sizes=\"(max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/webt\/51\/7f\/10\/517f10577e1ed9affa782650dd7c9f84.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/webt\/51\/7f\/10\/517f10577e1ed9affa782650dd7c9f84.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043f\u0443\u043d\u043a\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 PDB. \u0421\u0430\u043c\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u043d\u0435 \u043b\u043e\u0432\u0438\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0438 \u043d\u0435 \u043c\u0435\u043d\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043e\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0438 debugger, \u043e\u0442\u043a\u0443\u0434\u0430 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0430\u0441\u044c \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f.<\/p>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura.Furioso\/ComponentGenerationSourceMap.cs\" rel=\"noopener noreferrer nofollow\"><code>ComponentGenerationSourceMap.cs<\/code><\/a>;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Asaicraft\/Akbura\/blob\/feature\/diagnostics\/Akbura.Furioso\/ComponentGenerator.cs\" rel=\"noopener noreferrer nofollow\"><code>ComponentGenerator.cs<\/code><\/a>.<\/p>\n<\/li>\n<\/ul>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0430\u043a\u0431\u0443\u0440\u043e\u0439 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435, \u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0448 Dsl \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c. \u041c\u044b \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c \u0441\u0440\u0430\u0437\u0443 \u0441 Lsp \u0438 VisualStudio.<\/p>\n<\/div>\n<p>\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\/articles\/1066332\/\">https:\/\/habr.com\/ru\/articles\/1066332\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u0440\u043e\u0448\u0451\u043b(\u043e\u043f\u044f\u0442\u044c) \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043c\u0435\u0441\u044f\u0446 \u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0438. \u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443 \u0438 \u043d\u0430\u0443\u0447\u0438\u043b\u0438 Akbura \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043d\u044f\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0436\u0435 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u041f\u0438\u0448\u0435\u043c \u043f\u0430\u0440\u0441\u0435\u0440\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0431\u043b\u0435\u043d\u0434\u0435\u0440\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u043a\u0443\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u043c Language Server Protocol \u0438 \u0434\u0435\u043b\u0430\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0432 Visual Studio\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434\u0412\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u0434\u0430 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430, \u043d\u043e \u044d\u0442\u043e \u0442\u043e\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u043d\u0435\u0439\u0440\u043e\u0441\u043b\u043e\u043f, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u0430\u043b \u0418\u0418 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0438\u043c\u0435\u044f \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0438 Api. \u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043f\u043b\u0430\u0447\u0435\u0432\u043d\u044b\u0439, 33 \u0444\u0430\u0439\u043b\u0430 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u044c\u0441\u044f 2 \u043c\u0438\u043d\u0443\u0442\u044b \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u0441\u0431\u043e\u0440\u043a\u0438, \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u043d\u0443 \u043d\u0430 \u0442\u043e \u044d\u0442\u043e \u0438 \u0444\u0443\u0440\u0438\u043e\u0441\u0430\u0421\u0440\u0430\u0437\u0443 \u0443\u0442\u043e\u0447\u043d\u044e: \u043f\u043e\u0434 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u043e\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0438\u043c\u0435\u044e \u0432 \u0432\u0438\u0434\u0443 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u0421\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442. \u041f\u0430\u0440\u0441\u0435\u0440 \u0438 binder \u0443\u043c\u0435\u044e\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c diagnostics, \u043d\u043e \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u0431\u0435\u0440\u0451\u043c\u0441\u044f \u0434\u043e LSP.\u0421\u0435\u0439\u0447\u0430\u0441 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u0440\u0443\u0433\u0430\u044f. \u042f \u0445\u043e\u0447\u0443 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:\u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b Akbura \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442;\u043a\u0430\u043a \u043e\u043d\u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c;\u043a\u0430\u043a\u0438\u0435 \u0443 \u043d\u0438\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438;\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0438\u0445 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435;\u043f\u043e\u0447\u0435\u043c\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u043d\u043e\u0432\u0438\u043b\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e\u0434\u0440\u044f\u0434;\u0433\u0434\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u0432 .akbura-\u0444\u0430\u0439\u043b\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.\u0417\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432Akbura \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 Avalonia, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c visual tree \u0438 logical tree.\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0442\u044c Avalonia Developer Tools \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0441\u0451 \u0442\u0430\u043c. \u041d\u043e \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043e\u0432 Avalonia \u0438 \u0434\u0435\u0440\u0435\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 Akbura \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b.\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442:&lt;CounterPage&gt;    &lt;StackPanel&gt;        &lt;TextBlock Text={count} \/&gt;        &lt;Button Click={() =&gt; count++}&gt;            Increment        &lt;\/Button&gt;    &lt;\/StackPanel&gt;&lt;\/CounterPage&gt;\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f Avalonia \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0442 StackPanel, TextBlock, Button, \u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0441\u0442\u0438\u043b\u0438 \u0438 layout.\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f Akbura \u043d\u0430\u0441 \u0431\u043e\u043b\u044c\u0448\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0441\u0430\u043c CounterPage: \u0435\u0433\u043e state, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, injected services \u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.\u041e\u0434\u0438\u043d \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Akbura \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u043e. \u0415\u0441\u043b\u0438 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 visual tree, \u0433\u0440\u0430\u043d\u0438\u0446\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0431\u044b\u0441\u0442\u0440\u043e \u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f.\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:public interface IComponentTree{    IComponentTree? ComponentParent { get; }    IAvaloniaReadOnlyList&lt;IComponentTree&gt; ComponentChildren { get; }}\u041f\u043e\u043b\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 IComponentTree.cs.\u041a\u0430\u0436\u0434\u044b\u0439 AkburaControl \u0445\u0440\u0430\u043d\u0438\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:private readonly AvaloniaList&lt;IComponentTree&gt; _componentChildren = [];private IComponentTree? _componentParent;\u041a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u043a visual tree, \u043e\u043d \u0438\u0449\u0435\u0442 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u0433\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 IComponentTree:protected override void OnAttachedToVisualTree(    VisualTreeAttachmentEventArgs e){    base.OnAttachedToVisualTree(e);    SetComponentParent(FindComponentParent());    AkburaComponentRegistry.Attach(this);}\u041f\u0440\u0438 \u043e\u0442\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u044f\u0437\u044c \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f:protected override void OnDetachedFromVisualTree(    VisualTreeAttachmentEventArgs e){    base.OnDetachedFromVisualTree(e);    _useHooks.StopForDetach();    SetComponentParent(null);    AkburaComponentRegistry.Detach(this);}\u041f\u043e\u0438\u0441\u043a \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043f\u043e\u043a\u0430 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439:private IComponentTree? FindComponentParent(){    for (var parent = this.GetVisualParent();         parent != null;         parent = parent.GetVisualParent())    {        if (parent is IComponentTree componentParent)        {            return componentParent;        }    }    return null;}\u041c\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c\u0441\u044f \u043f\u043e visual tree, \u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b Akbura. \u0412 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435, \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e\u0435 \u0434\u0435\u0440\u0435\u0432\u043e:App\u251c\u2500\u2500 Navigation\u251c\u2500\u2500 Sidebar\u2514\u2500\u2500 Router    \u2514\u2500\u2500 CounterPage        \u2514\u2500\u2500 CounterButton\u0420\u0435\u0435\u0441\u0442\u0440 \u0436\u0438\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432\u041e\u0434\u043d\u043e\u0433\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f parent =&gt; children \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0443 \u0435\u0449\u0451 \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u043a\u0443\u0434\u0430-\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 AkburaComponentRegistry.\u0423\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u043e \u043e\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:internal static class AkburaComponentRegistry{    private static readonly object s_gate = new();    private static readonly List&lt;WeakReference&lt;AkburaControl&gt;&gt;        s_components = [];    internal static event EventHandler? Changed;    internal static void Attach(AkburaControl component)    {        lock (s_gate)        {            s_components.Add(                new WeakReference&lt;AkburaControl&gt;(component));        }        Changed?.Invoke(null, EventArgs.Empty);    }}\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e, \u0447\u0442\u043e \u0440\u0435\u0435\u0441\u0442\u0440 \u0445\u0440\u0430\u043d\u0438\u0442 \u043d\u0435 \u0441\u0430\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0430 WeakReference&lt;AkburaControl&gt;.\u0414\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u043e\u043c \u043c\u0443\u0441\u043e\u0440\u0430. \u0418\u043d\u0430\u0447\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043d\u0430\u0439\u0442\u0438 \u0443\u0442\u0435\u0447\u043a\u0443 \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u0430\u043c\u0430 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0443\u0442\u0435\u0447\u043a\u0443 \u043f\u0430\u043c\u044f\u0442\u0438, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0438\u0440\u043e\u043d\u0438\u0447\u043d\u043e.\u041f\u0440\u0438 \u0447\u0442\u0435\u043d\u0438\u0438 \u0440\u0435\u0435\u0441\u0442\u0440 \u0437\u0430\u043e\u0434\u043d\u043e \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0443\u0436\u0435 \u043c\u0451\u0440\u0442\u0432\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438:internal static ImmutableArray&lt;AkburaControl&gt;    GetAttachedComponents(){    lock (s_gate)    {        var builder =            ImmutableArray.CreateBuilder&lt;AkburaControl&gt;();        for (var index = 0;             index &lt; s_components.Count;)        {            if (s_components[index]                .TryGetTarget(out var component))            {                builder.Add(component);                index++;            }            else            {                s_components.RemoveAt(index);            }        }        return builder.ToImmutable();    }}\u0423 \u0440\u0435\u0435\u0441\u0442\u0440\u0430 \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u0435 Changed. \u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0433\u043e \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0434\u0435\u0440\u0435\u0432\u043e, \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f.\u041f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 AkburaComponentRegistry.cs.\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0421\u0430\u043c \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u044f \u0432\u044b\u043d\u0435\u0441 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 Akbura.Diagnostics.\u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043d\u0435 \u043d\u0443\u0436\u043d\u0430 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u0430\u043d\u0435\u043b\u044c \u0432 Release-\u0441\u0431\u043e\u0440\u043a\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Debug:using Akbura.Diagnostics;using Avalonia;public partial class App : Application{    public override void Initialize()    {        AvaloniaXamlLoader.Load(this);#if DEBUG        this.AttachAkburaDevTools();#endif    }}\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u043a\u043d\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e F12.\u0413\u043e\u0440\u044f\u0447\u0443\u044e \u043a\u043b\u0430\u0432\u0438\u0448\u0443 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c:#if DEBUGthis.AttachAkburaDevTools(options =&gt;{    options.ToggleGesture = new KeyGesture(        Key.F12,        KeyModifiers.Control);});#endif\u041e\u043a\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043a\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f classic desktop application lifetime.\u041e\u0442\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0441\u0430\u043c\u043e \u043e\u043a\u043d\u043e \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0438 \u0438\u0437 \u0440\u0435\u0435\u0441\u0442\u0440\u0430:AkburaComponentRegistry.ExcludeTopLevel(this);\u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u0443\u0432\u0438\u0434\u0438\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 DiagnosticsRoot, \u0434\u043e\u0431\u0430\u0432\u0438\u0442 \u0435\u0433\u043e \u0432 \u0434\u0435\u0440\u0435\u0432\u043e, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043d\u0430\u0447\u043d\u0451\u0442 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c \u0441\u0435\u0431\u044f. \u0417\u0432\u0443\u0447\u0438\u0442 \u0432\u0435\u0441\u0435\u043b\u043e, \u043d\u043e \u043f\u043e\u043b\u044c\u0437\u044b \u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e.\u0421\u0442\u0440\u043e\u0438\u043c \u0434\u0435\u0440\u0435\u0432\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0432\u0441\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:var components =    AkburaComponentRegistry        .GetAttachedComponents()        .Where(IsApplicationComponent)        .ToArray();\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u043a\u043e\u0440\u043d\u0438. \u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c, \u0435\u0441\u043b\u0438 \u0435\u0433\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043d\u0430\u0431\u043e\u0440\u0435:var componentSet = new HashSet&lt;AkburaControl&gt;(    components,    ReferenceEqualityComparer.Instance);var roots = components    .Where(component =&gt;        ((IComponentTree)component).ComponentParent            is not AkburaControl parent ||        !componentSet.Contains(parent))    .ToArray();\u0418\u0437 \u043a\u043e\u0440\u043d\u0435\u0439 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b TreeView.\u0414\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0438\u043c\u044f \u0442\u0438\u043f\u0430 \u0438 Name, \u0435\u0441\u043b\u0438 \u043e\u043d \u0437\u0430\u0434\u0430\u043d:private static string GetComponentDisplayName(    AkburaControl component){    var typeName = component.GetType().Name;    return string.IsNullOrWhiteSpace(component.Name)        ? typeName        : $&#187;{typeName}  #{component.Name}&#187;;}\u0427\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0440\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0430:Services;States;Parameters.\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e AkburaControl \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:internal ImmutableArray&lt;Parameter&gt;    GetDiagnosticParameters(){    return GetParameters();}internal ImmutableArray&lt;InjectService&gt;    GetDiagnosticServices(){    return GetServices();}internal ImmutableArray&lt;State&gt;    GetDiagnosticStates(){    return GetStates();}\u0421\u0435\u0440\u0432\u0438\u0441\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0414\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e injected service \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0435\u0433\u043e \u0442\u0438\u043f, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.\u041d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e:_selectedComponent.PropertyChanged +=    OnSelectedPropertyChanged;foreach (var state in         _selectedComponent.GetDiagnosticStates()){    state.ValueChanged += OnSelectedStateChanged;}\u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043e\u043a\u043d\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f state \u0438\u043b\u0438 Avalonia property.\u0418\u0437\u043c\u0435\u043d\u044f\u0435\u043c state \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0430 \u043b\u0435\u0442\u0443\u041f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e. \u041c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c state, \u043d\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0435\u0441\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 InputBuilder.\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 builders \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442:\u0441\u0442\u0440\u043e\u043a\u0438;\u0447\u0438\u0441\u043b\u0430;\u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438;\u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435.\u0423\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c TypeConverter, \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 Parse \u0438 TryParse, \u0430 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u2014 JSON.\u041f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 state \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 BoxedValue:value =&gt; state.BoxedValue = value\u041e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a Avalonia property:component.SetCurrentValue(property, value);\u0414\u043b\u044f read-only \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442, \u0430 \u043e\u0447\u0438\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0438 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0432 \u043d\u0435\u0451 \u043d\u043e\u0432\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b.\u041a\u0440\u043e\u043c\u0435 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439:this.AttachAkburaDevTools(options =&gt;{    options.InputBuilders.Insert(        0,        new RouteInputBuilder());});Builders \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443. \u041f\u0435\u0440\u0432\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u0447\u0435\u0440\u0435\u0437 selector.\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f Url \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 TextBox, \u0430 ComboBox \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.\u041f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u043a\u043d\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 DiagnosticsRoot.cs.\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u2014 \u044d\u0442\u043e \u0435\u0449\u0451 \u043d\u0435 \u0432\u0441\u044f \u0434\u0438\u0430\u0433\u043d\u043e\u0441\u0442\u0438\u043a\u0430\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u043d\u0430 \u0432\u043e\u043f\u0440\u043e\u0441 \u00ab\u0447\u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u00bb.\u041d\u043e \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b:\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043d\u044f\u043b\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f;\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0441\u044f Update;\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0448\u043b\u043e \u0437\u0430 \u043e\u0434\u0438\u043d batch;\u043a\u0430\u043a\u043e\u0439&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-489635","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/489635","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=489635"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/489635\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=489635"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=489635"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=489635"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}