Это копия, сохраненная 4 мая в 12:13.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
1. Ресурсы:
— https://dotnet.microsoft.com/learn
— https://ru.stackoverflow.com/a/416585/422180
— https://github.com/dotnet
— https://github.com/quozd/awesome-dotnet
— https://metanit.com
— https://professorweb.ru
2. С# для веба
— https://docs.microsoft.com/ru-ru/aspnet/core
3. C# для десктопа
— https://docs.microsoft.com/ru-ru/dotnet/desktop
4. С# для игор
— https://dotnet.microsoft.com/en-us/apps/games/engines
5. С# для мобильной разработки
— https://docs.microsoft.com/ru-ru/dotnet/maui]
Шапка: https://pastebin.com/HT7Hi6FD
Предыдущий: >>2920885 (OP)
ВНИМАНИЕ, в тред повадился срать джавадебил. Шарпочане, игнорируйте, а лучше репортите. Главное - не кормите.
Как там дела с работой на сишарпе? Когда уже продадите кабанчикам новый кросплатформенный c# 3000 который конечно же лучше джавы?
отлично с работой. пишем на последнем шарпе, а на старой жава которую "нельзя обновлять у нас тут все ыньтырпрайз и все сломаица"
>новый кросплатформенный c#
Да как нехуй делать. Пришел в середине 22-го года работать в контору. Был комплекс работающий на виндовых серверах, МССКЛ-е и на Core2.1.
Кабан сказал: "Ебать-ебать, надо импортозамещаться. Линукс-хуинукс, другая БД, очереди и вот это все".
Мы: "Ок, но надо поднимать до .net6, обновлять все фреймворки и т.д. Ну и на тайпскрипт до кучи. Иначе не заработает"
По итогу спокойно все перепилили и кайфуем. В этом году думаю и до .net8 очередь дойдет.
На подобии кликера. Ну там грабить корованы, но только в 2д.
Хорошая ли идея использовать Blazor? Я не совсем понимаю как это все должно работать на фронте.
Представляю себе так: blazor webassembly. На экране у юзера происходят действия, проигрывается анимация, юзер что то нажимает что то делает. При действиях кторые происходят редко например покупка чего то отправляются http запросы на сервер. А вот при нажатиях, например при игровых кликах, сборе чего либо, на клиенте происходит сбор этой информации и отправка её пачками например раз в 10 секунд. Так как мне кажется держать открытым подключения например в SignalR очень затратно и обрабатывать сервером ебищем кликов, хуй с ним 1 человек, а если 100 человек и каждый кликает.
И вот у меня вопрос, стоит ли ебатся с blazor webassembly ? Или взять например pixijs и на нем сделать клиент а серверную сторону уже на C#?
Я просто хз эти javascripты.
>А вот при нажатиях, например при игровых кликах, сборе чего либо, на клиенте происходит сбор этой информации и отправка её пачками например раз в 10 секунд.
Практически всё надо проводить через сервер, иначе у тебя моментально заведутся читеры.
Не надо заниматься преждевременной оптимизацией, дотнет может спокойно десятки, если не сотни, тысяч запросов в секунду обрабатывать. Пиши всё как есть, оптимизировать будешь, когда поймут проблемы.
Я не компетентен в этом вопросе. Жди, пока кто-то другой ответит.
По чистой архитектуре - у тебя вообще в Application не должно быть внешних зависимостей. Только логика и интерфейсы какие-то, которые будут на инфраструктурном слое реализованы(всякие там IZalupaRepository и прочее).
Единственная нормальная зависимость - это доменный слой, который уже точно ни от чего не зависит.
Логика-то всей этой херни в чем. Твой слой приложения - не должен зависить ни от фреймворка, ни от библиотек, ни от слоя доступа к данным. Ты должен иметь возможность - без лишних телодвижений взять и заменить всё, что не относится к логике. Если у тебя начинают появляться зависимости - тебе, если ты решишь сменить какую-то либу, придется изменять и Application.
Другое дело - иногда чисто следовать всем заветам чистой архитектуры - сложно. А иногда - не нужно, в контексте того, что проект не настолько здоровый, чтобы в случае надобности - переписать нужные куски.
>можно ли в слой Application добавлять сторонние библиотеки
Как архитектор скажет, так и будет.
>я уже успел туда FluentValidation поставить
Ну ты там и так уже насрал засунув контракты в Application, так что одним говном больше, одним меньше.
Как в DataGrid сделать по простому триггер чтобы при изменеии текста в какой-то ячейки в последнем столбце вставлялся текст?
То есть что я хочу - есть три столбца. пользователь меняет текст в ячейке и теперь в последнем столбце должен проставится чекбокс чтобы визуально было видно что вот в этой строке было изменение.
Хочу по умному через триггеры, а не говнокодом.
/тхеад
>сделать по простому
По простому — вещь относительная. Если у тебя подготовлена инфраструктура, то будет просто, а если нет, то делай через события.
Если ты делал все по MVVM-паттерну, то ты можешь в своей модели, являющейся строкой таблицы, реализовать интерфейс IChangeTracking.
Он по сути заставит твою модель реализовать булевое свойство IsChanged, к которому и будет привязываться твой чекбокс, сигнализирующий об изменении.
А дальше ты в нужных свойствах модели в блоке set указываешь
IsChanged = true;
Далее, как я понял встанет вопрос о сбросе флага, если к примеру база данных будет сохранена. Поэтому интерфейс помимо IsChanged требует реализовать метод AcceptChanges(), который сбрасывает флаг IsChanged до дефолта т.е.
public void AcceptChanges() => IsChanged = false;
Аналогичный вопрос на so:
https://stackoverflow.com/questions/2363801/what-would-be-the-best-way-to-implement-change-tracking-on-an-object
Как я понял, чтобы все флаги резетнуть при сохранении базы данных, нужно будет пройтись по всем экземплярам и запустить AcceptChanges(). Я не эксперт, но выглядит как хуйня.
1. А что если у меня каждое свойство должно иметь свой собственный идентификатор? Т.е. я должен выводить каждое такое свойство в отдельный класс, реализующий IChangeTracking.
2. Мне не нравится, что надо каждый раз обходить все данные, чтобы сбросить флаг.
3. Что если возникнет такая ситуация:
- В базе данных число 356
- Пользователь вводит число 128, и флаг IsChanged меняется на true
- Пользователь снова вводит число 356
В таких случаях маркер изменения должен сброситься т.к. оно равно исходному значению.
Почему к примеру не создавать временную точку при изменении данных ячейки? И создать точку сохранения базы данных. Далее какой нибудь мультибиндинг сравнивает обе временные точки и выдает булевый вердикт — являются ли данные новыми или нет.
Мне кажется, что такой вариант экономичнее, но у меня нет практики, чтобы утверждать подобное.
>сделать по простому
По простому — вещь относительная. Если у тебя подготовлена инфраструктура, то будет просто, а если нет, то делай через события.
Если ты делал все по MVVM-паттерну, то ты можешь в своей модели, являющейся строкой таблицы, реализовать интерфейс IChangeTracking.
Он по сути заставит твою модель реализовать булевое свойство IsChanged, к которому и будет привязываться твой чекбокс, сигнализирующий об изменении.
А дальше ты в нужных свойствах модели в блоке set указываешь
IsChanged = true;
Далее, как я понял встанет вопрос о сбросе флага, если к примеру база данных будет сохранена. Поэтому интерфейс помимо IsChanged требует реализовать метод AcceptChanges(), который сбрасывает флаг IsChanged до дефолта т.е.
public void AcceptChanges() => IsChanged = false;
Аналогичный вопрос на so:
https://stackoverflow.com/questions/2363801/what-would-be-the-best-way-to-implement-change-tracking-on-an-object
Как я понял, чтобы все флаги резетнуть при сохранении базы данных, нужно будет пройтись по всем экземплярам и запустить AcceptChanges(). Я не эксперт, но выглядит как хуйня.
1. А что если у меня каждое свойство должно иметь свой собственный идентификатор? Т.е. я должен выводить каждое такое свойство в отдельный класс, реализующий IChangeTracking.
2. Мне не нравится, что надо каждый раз обходить все данные, чтобы сбросить флаг.
3. Что если возникнет такая ситуация:
- В базе данных число 356
- Пользователь вводит число 128, и флаг IsChanged меняется на true
- Пользователь снова вводит число 356
В таких случаях маркер изменения должен сброситься т.к. оно равно исходному значению.
Почему к примеру не создавать временную точку при изменении данных ячейки? И создать точку сохранения базы данных. Далее какой нибудь мультибиндинг сравнивает обе временные точки и выдает булевый вердикт — являются ли данные новыми или нет.
Мне кажется, что такой вариант экономичнее, но у меня нет практики, чтобы утверждать подобное.
Ты занимаешься какой-то хуйней. Твоя строка таблицы биндится к какому-то объекту. При изменении текста изменится проперти этого объекта, вот там в сеттере и поменяй другое проперти, к которому ты забиндил чекбокс.
ну автор первоначального вопроса не посчитал нужным указать что там за ошибка, значит ему и решение ошибки не нужно. Так что глупо спрашивать его об ошибке
Я вообще не могу воспринимать код с ними. у меня какая-то агрессия и зубы скрипят
Эту хуйню придумали, чтобы код был похож на нодежс. Я не шучу. Когда дотнет стал терять популярность, какому-то менеджеру пришла в голову охуительная идея: давайте будем писать как на ноде, тогда все бросят ноду и перекатятся в дотнет. Ведь на ноде пишут только потому, что там нет void Main, в этом вся причина.
Потому что петушарп.
Импортозаместились опенсорсом как и все вокруг. Откуда столько вони?
>Импортозмещение с дотнетом?
Проект и так на дотнете был, просто на Core2.1, что по меркам шарпа уже легаси. Просто подняли версию до самой свежей LTS на тот момент.
Импортозамещать нужно было все остальное, что требует лицензий.
>Можно ли в таком случае пихать библиотеку в доменный слой?
Хуй знает, такое себе. Я классы с ошибками в слой контрактов запихиваю всегда. Почему чел на видео так же не сделал - хуй знает, тем более что у него есть в проекте Contracts, плюс ошибки не связаны с сущностями. Может какие-нибудь DDD заморочки мешают это сделать.
Алсо, слегка обзмеился с библиотеки. Кто-то явно решил выебнуться и вместо общепринятого Result и его производных, обозвать свой тип ErrorOr. Хотя может это и я отстал от тенденций.
Этот ютубер и есть автор ErrorOr. А вот библиотеку в домен я класть не буду, выглядит странно, особенно когда прочитал, что в доменный слой вообще зависимости класть хуёво.
У говноеда жабоида галлюцинации
Как такое разруливается?
Меняй приватные поля которые стоят за свойствами
Я пытаюсь сформировать ссылку с параметрами, и получить данные из этого запроса.
Если я просто указываю
("https://api.battlemetrics.com/servers/6803740")
все работает. Но последние цифры идут от пользователя, т.е. это переменная.
С нижеприведенными параметрами httpClient.GetFromJsonAsync код становится не рабочим.
("https://api.battlemetrics.com/servers/" + nums)
($"https://api.battlemetrics.com/servers/{nums}" )
Сука, какое нахуй может быть желание помогать если в проблемах "пук среньк не работаит", а не исключение с стэктрейсом
Нужно во-первых разобраться какого рода у тебя контент.
У тебя может быть модель для каждой страницы. Соответственно, каждая страница имеет свой уникальный тип.
К примеру у тебя страницы настроек приложения: CommonSettings, AppearanceSettings, KeyboardSettings.
Все эти страницы могут иметь общий интерфейс, к примеру IMySettings.
Далее, у тебя во вьюмодели есть свойство текущей страницы
IMySettings CurrentPage, куда ты и кидаешь экземпляр нужной страницы. Как ты это будешь делать на стороне вьюмодели — твое дело. К примеру это можно сделать при помощи команды, которая извлекает из словаря страниц нужную по строковому названию. Это название передается кнопкой команде при помощи CommandParameter.
Еще раз. Кнопка во вью вызывает команду ChangePageCommand с параметром CommandParameter="AppearanceSettings". Команда ищет в словаре страниц экземпляр модели IMySettings по ключу "AppearanceSettings" и пихает в свойство CurrentPage энтот экземпляр.
А что дальше? А дальше ты создаешь во вью ContentPresenter, к которому к свойству Content привязываешь свойство CurrentPage из вьюмодели. Но ничего не произойдет (максимум отобразит тип текущего экземпляра в CurrentPage), потому что ContentPresenter не понимает каким образом эти данные отображать.
И тут в игру вступают шаблоны данных, или DataTemplate.Эти шаблоны ты настраиваешь в своем ContentPresenter, каждое каждое вью соответствует определенному типу модели.
К примеру ты создаешь CommonSettingsPage : UserControl, который будет соответствовать типу CommonSettings.
<DataTemplate DataType="{x:Type models:CommonSettings}">
<views:CommonSettingsPage />
</DataTemplate>
И так далее для всех страниц. С этого момента ContentPresenter уже автоматом подбирает соответствующую вью под текущий экземпляр модели в CurrentPage.
Собсно вот, это простой пример.
>ContentPresenter
Точнее ContentControl. Я их вечно путаю.
Его обычно используют, когда речь заходит о шаблонах данных. Он может отобразить элемент в единственном экземпляре.
Есть еще ItemsControl, который позволяет вывести список разношерстных данных. К примеру так устроено окно свойств в вижуал студии. Посмотри на прикрил. Окно не знает что в него впихнут и в каком порядке. Тут настроен шаблон данных не для всей страницы, а для каждого типа: double, string, Brush, Thickness, CornerRadius и т.д.
Далее список просто отображается в соответствии с шаблоном каждого итема. Там же можно настроить группировку, сортировку, поиск и т.д.
Скрин 1. Я создал вьюмодель с тестовыми свойствами разного типа: Double, Thickness, Point
чтобы показать, что проблема только с Point
Скрин 2. Я создал вью и привязал данные вью модели. Тут два блока. В первом я привязал данные как есть, без редактирования культуры. Во втором блоке я привязывался к тем же значениям, но с указанием конкретной культуры: ru-RU.
Собсно на превью окна слева можно заметить, как разделители поменялись. Т.е. конвертация всех значений в string отрабатывает нормально.
Далее я запускаю приложение и пытаюсь изменять значения в каждом текстбоксе. Первый блок (тот, что без изменения культуры) по всем трем значениям отрабатывает хорошо. Во втором блоке без проблем обратно конвертируют Double и Thickness. А вот Point выдает исключение (в окне указал красным проблемный элемент):
System.Windows.Data Error: 7 : ConvertBack cannot convert value '36,6;48,7' (type 'String'). BindingExpression:Path=TestPointValue; DataItem='MainViewModel' (HashCode=48832851); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: The input string '6;48' was not in a correct format.
at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, ReadOnlySpan`1 value, TypeCode type)
at System.Convert.ToDouble(String value, IFormatProvider provider)
at System.Windows.Point.Parse(String source)
at System.Windows.PointConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)
at MS.Internal.Data.SourceDefaultValueConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'
Скрин 1. Я создал вьюмодель с тестовыми свойствами разного типа: Double, Thickness, Point
чтобы показать, что проблема только с Point
Скрин 2. Я создал вью и привязал данные вью модели. Тут два блока. В первом я привязал данные как есть, без редактирования культуры. Во втором блоке я привязывался к тем же значениям, но с указанием конкретной культуры: ru-RU.
Собсно на превью окна слева можно заметить, как разделители поменялись. Т.е. конвертация всех значений в string отрабатывает нормально.
Далее я запускаю приложение и пытаюсь изменять значения в каждом текстбоксе. Первый блок (тот, что без изменения культуры) по всем трем значениям отрабатывает хорошо. Во втором блоке без проблем обратно конвертируют Double и Thickness. А вот Point выдает исключение (в окне указал красным проблемный элемент):
System.Windows.Data Error: 7 : ConvertBack cannot convert value '36,6;48,7' (type 'String'). BindingExpression:Path=TestPointValue; DataItem='MainViewModel' (HashCode=48832851); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') FormatException:'System.FormatException: The input string '6;48' was not in a correct format.
at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, ReadOnlySpan`1 value, TypeCode type)
at System.Convert.ToDouble(String value, IFormatProvider provider)
at System.Windows.Point.Parse(String source)
at System.Windows.PointConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)
at MS.Internal.Data.SourceDefaultValueConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)'
Ах да, если я в последний текстбокс буду вносить данные как если бы там не была указана культура, то ошибки обратной конвертации не возникнет.
Т.е. вместо '35,6;48,7' я буду писать '35.6,48.7' то будет все норм.
Ну и в чем я не прав?
>Т.е. вместо '35,6;48,7' я буду писать '35.6,48.7' то будет все норм.
Попробуй 35.6;48.7 ради эксперимента
не пробовал просто строку в отдельной переменной конкатнуть затем кинуть в запрос?
Не работает. Нужны символы InvariantCulture.
При этом в Thickness принцип тот же и все распознается.
Основная проблема в том, как распознается разделитель данных на основе культуры. Пытался посмотреть исходник, но там что-то мудреное из internal классов.
Пробовал, та же картина.
Зачем используется какой-то там TokenizerHelper, если сепаратор списка можно получить так:
cultureInfo.TextInfo.ListSeparator
Машин лёрнинг модели, тысячи их ёпта.
https://huggingface.co/models?pipeline_tag=automatic-speech-recognition&sort=trending
static void Main()
{
//
Dictionary<string, List<List<string>>> result = Parsing(url: "https://www.readfootball.com/tables.html");
if(result != null)
{
foreach(var item in result)
{
Console.WriteLine(item.Key);
Console.WriteLine("___________________________");
item.Value.ForEach(r=> Console.WriteLine(string.Join("\t", r)));
Console.WriteLine(item.Value);
}
}
}
private static Dictionary<string, List<List<string>>> Parsing(string url)
{
try
{
Dictionary<string, List<List<string>>> result = new Dictionary<string, List<List<string>>>();
using (HttpClientHandler hdl = new HttpClientHandler {AllowAutoRedirect = false, AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.None })
{
using (var clnt = new HttpClient(hdl))
{
using (HttpResponseMessage resp = clnt.GetAsync(url).Result)
{
if (resp.IsSuccessStatusCode)
{
var html = resp.Content.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(html))
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var tables = doc.DocumentNode.SelectNodes(".//div[@class='block_content']//div[@class = 'two-table-row']//div[@class]");
if(tables != null && tables.Count > 0)
{
foreach(var table in tables)
{
var titelN = table.SelectSingleNode(".//div[@class = 'head_tb']"); //Заголовок таблицы на сайте
if (titelN != null)
{
var tbl = table.SelectSingleNode(".//div[@class = 'tab_champ']//table");
if (tbl != null) //Тут уже берём строки
{
var rows = tbl.SelectNodes(".//tr");
if (rows != null)
{
var res = new List<List<string>>();
foreach (var row in rows)
{
var cells = row.SelectNodes(".//tr");
if (cells != null)
{
res.Add(new List<string>(cells.Select(c => c.InnerText)));
//Console.WriteLine(e);
}
}
result[titelN.InnerText] = res;
}
}
}
}
return result;
}
else
{
Console.WriteLine("Нет таблиц");
}
}
}
}
//Console.WriteLine("Hello, World!");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
}
Код один в один же написан, что не так?
static void Main()
{
//
Dictionary<string, List<List<string>>> result = Parsing(url: "https://www.readfootball.com/tables.html");
if(result != null)
{
foreach(var item in result)
{
Console.WriteLine(item.Key);
Console.WriteLine("___________________________");
item.Value.ForEach(r=> Console.WriteLine(string.Join("\t", r)));
Console.WriteLine(item.Value);
}
}
}
private static Dictionary<string, List<List<string>>> Parsing(string url)
{
try
{
Dictionary<string, List<List<string>>> result = new Dictionary<string, List<List<string>>>();
using (HttpClientHandler hdl = new HttpClientHandler {AllowAutoRedirect = false, AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.None })
{
using (var clnt = new HttpClient(hdl))
{
using (HttpResponseMessage resp = clnt.GetAsync(url).Result)
{
if (resp.IsSuccessStatusCode)
{
var html = resp.Content.ReadAsStringAsync().Result;
if (!string.IsNullOrEmpty(html))
{
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
var tables = doc.DocumentNode.SelectNodes(".//div[@class='block_content']//div[@class = 'two-table-row']//div[@class]");
if(tables != null && tables.Count > 0)
{
foreach(var table in tables)
{
var titelN = table.SelectSingleNode(".//div[@class = 'head_tb']"); //Заголовок таблицы на сайте
if (titelN != null)
{
var tbl = table.SelectSingleNode(".//div[@class = 'tab_champ']//table");
if (tbl != null) //Тут уже берём строки
{
var rows = tbl.SelectNodes(".//tr");
if (rows != null)
{
var res = new List<List<string>>();
foreach (var row in rows)
{
var cells = row.SelectNodes(".//tr");
if (cells != null)
{
res.Add(new List<string>(cells.Select(c => c.InnerText)));
//Console.WriteLine(e);
}
}
result[titelN.InnerText] = res;
}
}
}
}
return result;
}
else
{
Console.WriteLine("Нет таблиц");
}
}
}
}
//Console.WriteLine("Hello, World!");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}
}
Код один в один же написан, что не так?
Это троллинг?
Что не так, чел не насрал вместо одного метода десяток классов с однострочными методами как дядя хуйло в клин коде завещал?
Он насрал миллион скобок.
Вот сука первое на что падает глаз это диспоуз хттпКлиента и куча лишней вложенности которая нахуй не нужна
Все эти continue не нужны, их можно заменить на ?. с финальной проверкой на null. Кроме последнего, его надо просто выкинуть, инвертировав if обратно.
Точнее последний цикл, где res, надо через Linq переписать.
много уровней - не знает про инвертирование if
Async().Result - сразу кастрировать
высрал портянку где код делает все - и запрос в сеть и парсинг
грязный метод - срет в консоль вместо кидания ошибки
возращает нулл при ошибке
создает хттпклиент на месте
уебищный шрифт
Че мне прописать что бы на сайте были категории?
Пример
zlypa.com/bmv/kek.html
zlypa.com/lada/4ebyrec.html
Категории хранятся в бд.
Что поменять или добавить что бы один контролёр отвечал за категории?
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
Осуждаю фронт на шарпах но вот https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-8.0
Да я читал это всё, я не могу додуматься как это всё применить.
Собственно по этому тут и спрашиваю
> Пишу фронт на блейзере че таково то епт
То что КАЖДАЯ, блядь, попытка делать фронт на шарпах заканчивается тем, что тебе теперь надо ОХУЕТЬ как изучить как это у майков работает и вникнуть как сделать то что на обычном жс за 2 минуты.
Ну серьезно. Если выходим за круды, а начинаются всякие вебсокеты, какие-то графики динамические, прочее-прочее, ты просто страдаешь, страдаешь. А если приложение еще и раздрастается - тебе приходится кучу хуйни сверху допиливать.
Ну и в результате - каждый раз - проще было писать клиент сразу на чем угодно, но не на шарпе.
Да действительно хуйня получится, я тогда не смогу нормально сделать /admin/ , придётся чета снова выдумывать.
Ну сделаю тогда просто контроллер Category
Даже не знаю, сейчас после обновы много положительных отзывов слышал о блейзере.
Думаешь стоит учить джава скрипт + фреймоврк тупо для пет проджекта?
Вот я привязываю свойство. По каким критериям происходит обновление, если я к примеру в это свойство кидаю новый экземпляр объекта?
И почему в некоторых случаях обновление происходит даже если я меняю свойство внутри объекта, а не объект в привязываемом свойстве?
Вот смотри, у меня есть dp-свойство MyBrush. Туда я помещаю экземпляр GradientBrush.
Потом я беру и в этом экземпляре меняю цвет градиента:
MyBrush.GradientStops[0].Color = Colors.Red;
После чего срабатывает событие изменения MyBrush. Почему?
Я не менял сам MyBrush, я менял свойства находящегося там экземпляра. Я понимаю, если бы я привязался к MyBrush.GradietnStops[0].Color (невозможно, но представим). Тогда была бы хоть какая-то логика: меняется свойство -> вызывается событие связанное с изменением конкретно этого свойства -> обновляются привязки.
И вот твой ответ про INPC и dp становится не таким-то и очевидным. Есть что-то еще, что вызывает события, и самое главное почему привязка на них подписывается?
В классе GradientBrush есть событие Changed, которое и срабатывает при любом внутреннем изменении чего либо, но почему оно влияет на вызов события изменения свойства MyBrush?
Тебе бы основы подтянуть, анон. Почитать про то, чем классы отличаются от структур, о передаче по ссылке и по значению
https://learn.microsoft.com/en-us/archive/msdn-magazine/2008/september/foundations-dependency-properties-and-notifications
Читай главу
The Freezable Difference
>даже шапку сделать не можете куда вам с великой джавой тягаться?
Жабоёб прям даже не знает до чего ещё доебаться.
Прочитал, интересная статья. Там описано, что Freezable переопределяет событие OnPropertyChanged. Теперь я понял почему возникает событие Changed, если я что-то внутри изменил и почему у этого события нет пояснения что конкретно было изменено.
Но я все еще не понимаю кто в биндинге привязывается к событию Changed. Вернемся к моему примеру, я тут подробнее расписал класс:
public class MyClass : INotifyPropertyChanged
{
. . private Brush myBrush;
. . public Brush MyBrush
. . {
. . . . get {
. . . . . . . . return myBrush;
. . . . . }
. . . . . set {
. . . . . . . myBrush = value;
. . . . . . . PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyBrush)));
. . . . . }
. . }
. . public event PropertyChangedEventHandler? PropertyChanged;
}
Когда я привязываюсь к MyClass.MyBrush, привязка отслеживает событие MyClass.PropertyChanged, она не отслеживает MyBrush.Changed. Ей должно быть вообще плевать что в MyBrush хранится и что с ним происходит.
Почему, когда я делаю это:
MyBrush.GradientStops[0].Color = Colors.Red;
Срабатывает не только событие MyBrush.Changed, но и MyClass.PropertyChanged?
Надо, короче, запруфать это безобразие.
Прочитал, интересная статья. Там описано, что Freezable переопределяет событие OnPropertyChanged. Теперь я понял почему возникает событие Changed, если я что-то внутри изменил и почему у этого события нет пояснения что конкретно было изменено.
Но я все еще не понимаю кто в биндинге привязывается к событию Changed. Вернемся к моему примеру, я тут подробнее расписал класс:
public class MyClass : INotifyPropertyChanged
{
. . private Brush myBrush;
. . public Brush MyBrush
. . {
. . . . get {
. . . . . . . . return myBrush;
. . . . . }
. . . . . set {
. . . . . . . myBrush = value;
. . . . . . . PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyBrush)));
. . . . . }
. . }
. . public event PropertyChangedEventHandler? PropertyChanged;
}
Когда я привязываюсь к MyClass.MyBrush, привязка отслеживает событие MyClass.PropertyChanged, она не отслеживает MyBrush.Changed. Ей должно быть вообще плевать что в MyBrush хранится и что с ним происходит.
Почему, когда я делаю это:
MyBrush.GradientStops[0].Color = Colors.Red;
Срабатывает не только событие MyBrush.Changed, но и MyClass.PropertyChanged?
Надо, короче, запруфать это безобразие.
>Срабатывает не только событие MyBrush.Changed, но и MyClass.PropertyChanged
не подтверждаю такое поведение.
перечитывется {Binding MyClass.MyBrush - да, но INPC для MyClass не дергается
Мимо опыт есть
Зато срабатывает конвертер
Пикрил 1 - мой конвертер, который просто извлекает цвет из второй точки градиента. В методе конвертации и обратной конвертации я печатаю сообщение, сигнализирующее о срабатывании метода.
Пикрил 2 - привязываю градиент из MyBrush к бэкграундам двух прямоугольников. К одному из них привязка осуществляется через конвертер из пикрил 1
Далее видеорил, где я нажатием кнопки меняю вторую точку градиента. Как видно, каждое изменение точки градиента почему-то запускает метод Convert. Разве конвертер не запускается при событии MyClass.PropertyChanged?
В конвертере опечатка. Там действительно меняется вторая точка градиента, просто скрин взял неактуальный:
return ((LinearGradientBrush)value).GradientStops[1].Color;
Что делать если мне нравится платформа .NET, но все говорят что он никому не нужен и лучше учить PHP для быстрого вката в индустрию чтобы потом перейти на современный Go?
Решил продублировать тут чтобы узнать мнение у работающих уже на сишарпе.
Тебе в МВП
Твой Convert пишет потому что Binding MyBrush это бинлинг к фризабле и конечно при любом изменении внутри фризаблы он перечитывается.
INPC у MyClass при этом нерушим - некому его вызывать
>Binding MyBrush это бинлинг к фризабле
А какого черта конвертер прилип к содержимому свойства MyBrush, а не к событию MyClass? Ничего не понимаю.
В моем понимании конвертер должен отработать только когда сработает обновление привязки, а оно сработает только если вызовется событие MyClass.PropertyChanged.
Ерунда какая-то.
Мне хочется писать на том что нравится, дотнет почти все мои хотелки закрывает. Но и слезть с маминой шеи хочется быстрее.
>Кто эти 'все'? Они с тобой сейчас в одной комнате?
В дискорде)
>А какого черта конвертер прилип к содержимому свойства MyBrush, а не к событию MyClass
Смотри же свой биндинг
{Binding MyBrush, Converter={StaticResouce GradientStopCnv}
то есть ты создал биндинг к MyBrush да с конвертером.
>В моем понимании конвертер должен отработать только когда сработает обновление привязки
ты плохо читал статью.
MyBrush будет вызывать INPC и обновление если ты сделаешь MyClass.MyBrush=new(...), потому что сработает INPC у MyClass - то есть классический подход к нотификации
Но MyBrush является Freezable и биндинг подписывается дополнительно на ченжед. И когда ты меняешь что-то внутри MyBrush, то биндинг ловит события ченджед и ПЕРЕЧИТЫВАЕТ свойство MyBrush попутно дергая конвертер, который находится в том же биндинге. А механизм INPC вообще никак не затрагивается.
>ну и не забывай - кистей не должно быть во вьюмоделях если у тебя они из MVVM
А как же мне хранить настройки, темы и прочее? Почему нельзя хранить?
>>17226
>MyBrush будет вызывать INPC и обновление
INPC это интерфейс, а вызывать будет PropertyChanged, на которое биндинг и подписан. Когда событие вызывается, биндинг смотрит на аргументы события и если там значится имя ожидаемого свойства, то тогда привязка обновляется.
> если ты сделаешь MyClass.MyBrush=new(...), потому что сработает INPC
Вот именно, любое говно, проходящее через сеттер просто вызовет событие. Все еще непонятно про чем тут статус Freezable.
>Но MyBrush является Freezable и биндинг подписывается дополнительно на ченжед.
Вот это я и пытаюсь выяснить. В статье этого факта не увидел. Оказывается идет дополнительная подписка, что вроде как похоже на правду. Но для чего? Все, кто получил экземпляр кисти и так подписан на Changed, а в данном случае в MyBrush интересует только изменение экземпляра.
И еще одна странная особенность. Почему то это не работает с ConverterBack.
Ради эксперимента я связал два свойства через конвертер. В первое свойство помещается экземпляр кисти, далее конвертер получает этот экземпляр в методе Convert, клонирует его и отправляет во второе свойство. Я ожидаю, что если во втором свойстве вызвать событие Changed, то это вызовет метод ConverterBack. Но нет.
>Почему нельзя хранить?
потому что вьюмодель ничего не знает о виде. Пиши их держа в уме установку - вьюмодели можно безопасно вынести в сборку, где нет ссылки на System.Windows и другие WPF штуки. Ну и можно в любой момент выбросить WPF и сделать консольный гуи без переделок вьюмоделей
>А как же мне хранить настройки, темы и прочее
настройки разные бывают. настройки приложения конечно же доступны во вьюмоделях. А вот настройки вида (позиция и размер окон и кто его знает что ты там еще придумаешь) - нет
вьюмодели это "что отображать"
вид это "как отображать"
что где доступно разделяй по этому принципу
> проходящее через сеттер просто вызовет событие. Все еще непонятно про чем тут статус Freezable.
вот только ты НЕ вызываешь сеттер, поэтому механизм INPC бездействует. А работает дополнительный механизм подписки на ченджед, который присущ Freezable. Таким образом, биндинг перечитывает MyBrush, но сеттер с его INPC вообще не причем
>В статье этого факта не увидел
в статье прямо говорится что фризабле используют другой механизм уведомлений. Это ты почему то лепишь им INPC и пытаешься связать с INPC в MyClass, хотя они никак не связаны.
>а в данном случае в MyBrush интересует только изменение экземпляра
хз о чем ты. но суть проста
вызовешь сеттер - биндинг увидит INPC нотификацию и перечитает
изменишь внутри кисти что то - биндинг увидит ченжед и перечитает
>отправляет во второе свойство
это сеттер, то есть INPC
>вызовет метод ConverterBack
хз как у тебя сеттер вообще должен вызывать ConverterBack
ConverterBack вызается в виде из контролов при двустороннем биндинге
>Почему нельзя хранить?
потому что вьюмодель ничего не знает о виде. Пиши их держа в уме установку - вьюмодели можно безопасно вынести в сборку, где нет ссылки на System.Windows и другие WPF штуки. Ну и можно в любой момент выбросить WPF и сделать консольный гуи без переделок вьюмоделей
>А как же мне хранить настройки, темы и прочее
настройки разные бывают. настройки приложения конечно же доступны во вьюмоделях. А вот настройки вида (позиция и размер окон и кто его знает что ты там еще придумаешь) - нет
вьюмодели это "что отображать"
вид это "как отображать"
что где доступно разделяй по этому принципу
> проходящее через сеттер просто вызовет событие. Все еще непонятно про чем тут статус Freezable.
вот только ты НЕ вызываешь сеттер, поэтому механизм INPC бездействует. А работает дополнительный механизм подписки на ченджед, который присущ Freezable. Таким образом, биндинг перечитывает MyBrush, но сеттер с его INPC вообще не причем
>В статье этого факта не увидел
в статье прямо говорится что фризабле используют другой механизм уведомлений. Это ты почему то лепишь им INPC и пытаешься связать с INPC в MyClass, хотя они никак не связаны.
>а в данном случае в MyBrush интересует только изменение экземпляра
хз о чем ты. но суть проста
вызовешь сеттер - биндинг увидит INPC нотификацию и перечитает
изменишь внутри кисти что то - биндинг увидит ченжед и перечитает
>отправляет во второе свойство
это сеттер, то есть INPC
>вызовет метод ConverterBack
хз как у тебя сеттер вообще должен вызывать ConverterBack
ConverterBack вызается в виде из контролов при двустороннем биндинге
>хз как у тебя сеттер вообще должен вызывать ConverterBack
пикрил — то что я имею ввиду
>в статье прямо говорится что фризабле используют другой механизм уведомлений.
И что? Это не должно ебать привязку, которая слушает событие контейнера, а не событие содержимого контейнера. Это вообще выходит за рамки компетенции привязки. Какого хуя вообще?
Привязка это доставщик. Я ему дал коробку и сообщил эту коробку отнести, его не должно волновать что там внутри коробки. Вскрывается только на таможне и в конце пути.
>System.Windows
Ну это жестко. Слишком жестко. Это мне че, переписывать все библиотеки? У меня жизни не хватит. Но суть понял.
>настройки приложения
Настройки внешнего вида. Цветовая схема хранится как файл настроек, дальше загружается во вьюмодель настроек в виде словаря кистей.
Конечно, на каком-то этапе ты можешь хранить RGB данные, но там куча всего нужно: трансформации, градиенты, текстуры. По сути нужно переизобретать свою собственную кисть и потом ее конвертировать в оригинал. А сколько таких данных? Кошмарное количество.
Идея понятна, но такой подход для богатеньких.
>в статье прямо говорится что фризабле используют другой механизм уведомлений.
Вот как только я подпишусь на изменение свойства фризабле класса, вот тогда пусть этот способ и использует. А пока что я подписался на изменение свойства в котором этот класс хранится.
Я не знаю как мне еще донести свою мысль.
>пикрил — то что я имею ввиду
ну значит ты не понимаешь как ты подписался. Потому что ConverterBack вызывает биндинг, а для этого этот биндинг должен быть,причем биндинги требуют dp, то есть твой MyBrushB должно быть минимум dp, а вот MyBrushA уже просто свойством
>обытие контейнера, а не событие содержимого контейнера.
она слушает все. что поменяешь, то и услышит. Результат будет одинаковый в твоем случае
>переписывать все библиотеки
вьюмодели обычно в приложении, а не в либах.
Сам я использую feature namespace, то есть у меня вьюмодели и вид лежат вместе, а не в тупых папках Views/ViewModels
Но я знаю что никогда не буду переписывать вид на другой
И даже в этом случае я пишу вьюмодели как будто WPF не существует.
>Идея понятна, но такой подход для богатеньких
Какой такой. У тебя будет тот же код, просто он будет в слое вида, а не во вьюмоделях.
>>17616
> А пока что я подписался на изменение свойства в котором этот класс хранится.
ну может где то и подписался, но в твоем посте с картинками и видео - этого нет. Там просто биндинг на свойство.
>MyBrushB должно быть минимум dp, а вот MyBrushA уже просто свойством
Оба свойства - dp
>она слушает все.
Пиздеж, ща проверю. Вряд ли обновится привязка если я вызову кастомное событие внутри кастомного класса.
>Результат будет одинаковый в твоем случае
Результат вообще не одинаковый. Это вызывает ненужные события, которые приходится подавлять в конвертере. В них нет смысла. Всем, кому надо перерисовать кисть, и итак подписаны на Changed кисти. Я просто боюсь представить сколько перерисовок это вызывает, если бы я не вскрыл сей факт это в ковертере. Тупейшая хрень.
Воспринимаю это как побочку от каких-то других решений, о которых я пока не знаю.
>И даже в этом случае я пишу вьюмодели как будто WPF не существует.
Возможно тебе не приходилось, учитывая что многие ИТТ избегают фронтенд. У меня шейпы, кисти, да даже банальный Point это все систем виндовс.
> А пока что я подписался на изменение свойства в котором этот класс хранится.
Это продолжение темы почему привязка не должна подписываться на события экземпляра свойства. Это превышение ее полномочий.
Короче, я устал писать одно и то же. Мы похоже не понимаем друг друга.
>Оба свойства - dp
я обычно никогда биндинги вручную не пишу, но вообще там же еще есть триггеры "обновления назад" типа смена фокуса вызывает обновление привязки, не забывай об этом.
может в биндинге из кода нужно вручную вызвать обновление ибо никакой смены фокуса нет.
>если я вызову кастомное событие внутри кастомного класса.
ты о чем вообще
биндинг слушает INPC и в случаее фризабле еще слушает фризабловый ченджед
>Результат вообще не одинаковый
одинаковый - в обоих случаях кисть будет полностью перечитана
ну да, необдуманное использование вызывает много перерисовок. Ну на то они и фризабле что подразумевается иммутабельность с которой жить проще - какой смысл знать тебе в привязке что на 3 слоя ниже поменялось свойство Foo? Что тебе делать с этим знанием? Это вообще интернал объект и все, что ты можешь - перечитать всё заново.
Не меняй ты внутренности кисти, а меняй ты всю кисть - никогда бы и не знал про фризабле тонкости.
>Возможно тебе не приходилось
мне как приходилось. WPF это мой основной доход
>У меня шейпы, кисти, да даже банальный Point это все систем виндовс.
верно. но это знает вид, а вьюмоделям до этого дела нет.
вьюмодель хранит данные, допустим список имен "вася, петя, коля" то есть "ЧТО отображать", но ей плевать какой там будет шрифт, фон, цвет шрифта, размер итема в списке, выравнивание, отступ и так далее - этим занимается ВИД с его ответом на вопрос "КАК отображать"
А потому если класс имеет суффикс ViewModel, то в нем ничего этого быть не должно
>Это превышение ее полномочий
полномочия биндинга - подписаться на INPC + ченджед для фризабле. Не нравится? пиши свой биндинг или не меняй фризабле изнутри и будет тебе счастье и покой.
в конце концов ты можешь выставить свойство с нужными тебе кишками во вьюмоели (ну на самом деле не во вьюмоделе, а в стейте), можешь сделать конвертер который выдерет тебе из MyClass нужное. Или же смириться с природой фризабле
ты сам выбираешь стул
ты уже выбрал один стул - WPF, теперь выбирай где присесть
>Оба свойства - dp
я обычно никогда биндинги вручную не пишу, но вообще там же еще есть триггеры "обновления назад" типа смена фокуса вызывает обновление привязки, не забывай об этом.
может в биндинге из кода нужно вручную вызвать обновление ибо никакой смены фокуса нет.
>если я вызову кастомное событие внутри кастомного класса.
ты о чем вообще
биндинг слушает INPC и в случаее фризабле еще слушает фризабловый ченджед
>Результат вообще не одинаковый
одинаковый - в обоих случаях кисть будет полностью перечитана
ну да, необдуманное использование вызывает много перерисовок. Ну на то они и фризабле что подразумевается иммутабельность с которой жить проще - какой смысл знать тебе в привязке что на 3 слоя ниже поменялось свойство Foo? Что тебе делать с этим знанием? Это вообще интернал объект и все, что ты можешь - перечитать всё заново.
Не меняй ты внутренности кисти, а меняй ты всю кисть - никогда бы и не знал про фризабле тонкости.
>Возможно тебе не приходилось
мне как приходилось. WPF это мой основной доход
>У меня шейпы, кисти, да даже банальный Point это все систем виндовс.
верно. но это знает вид, а вьюмоделям до этого дела нет.
вьюмодель хранит данные, допустим список имен "вася, петя, коля" то есть "ЧТО отображать", но ей плевать какой там будет шрифт, фон, цвет шрифта, размер итема в списке, выравнивание, отступ и так далее - этим занимается ВИД с его ответом на вопрос "КАК отображать"
А потому если класс имеет суффикс ViewModel, то в нем ничего этого быть не должно
>Это превышение ее полномочий
полномочия биндинга - подписаться на INPC + ченджед для фризабле. Не нравится? пиши свой биндинг или не меняй фризабле изнутри и будет тебе счастье и покой.
в конце концов ты можешь выставить свойство с нужными тебе кишками во вьюмоели (ну на самом деле не во вьюмоделе, а в стейте), можешь сделать конвертер который выдерет тебе из MyClass нужное. Или же смириться с природой фризабле
ты сам выбираешь стул
ты уже выбрал один стул - WPF, теперь выбирай где присесть
>я обычно никогда биндинги вручную не пишу, но вообще там же еще есть триггеры "обновления назад"
Я биндил через xaml. По умолчанию "Two Sided", но я пробовал ставить явно. Не хочет работать. В обратную сторону работает только INPC, т.е. когда я меняю экземпляр кисти, но вот на события Changed не реагирует.
Короче, для меня вот эта магия остается непонятной.
Т.е. с одной стороны отслеживается оба события INPC + ченджед для фризабле, а с другой стороны только одно INPC.
>одинаковый - в обоих случаях кисть будет полностью перечитана
Выглядит так, как будто будет пересчитана дважды. Когда ты помещаешь кисть к примеру в свойство бэкграунда кнопки, то там идет подписка на Changed.
Если ты привязываешь кисть, что привязка тоже подписывается на Changed.
Получается двойное обновление.
>но это знает вид, а вьюмоделям до этого дела нет.
Но как-то информацию в вьюмодели надо хранить. Где хранить к примеру координаты чего либо? Или вот есть задача сделать векторный редактор. Нужно хранить список выделенных объектов. Где эти кривые хранить?
История действий, слои, корзина и прочее — все должно относиться ко вьюмодели, но при этом должно хранить информацию о кривой, которая относится к неймспейсу System.Windows
>но ей плевать какой там будет шрифт, фон, цвет шрифта
Если это не приколоченный гвоздями интерфейс, то в любом более или менее нормальном приложении, "Appearance" это один из разделов настроек, в котором хранятся и кисти, и размер шрифта и название шрифта. Хотя я не видел, чтобы эти данные были сложными, в основном это простейшие типы, максимум Color.
>но вот на события Changed не реагирует
ну технически это верно. что он может поменять в иммутабле объекте? ничего же
А INPC - там обычное свойство с сеттерами.
>Получается двойное обновление.
как и везде. каждая подписка работает независимо
>Нужно хранить список выделенных объектов. Где эти кривые хранить?
в стейте. то есть внутри контрола как угодно храни.
все контролы хранят внутри себя и наружу только некоторые свойства выставляют.
>хранить информацию о кривой
ага, информацию. но не саму кривую. И то не факт.
вьюмодели - не вид и не должны знать о рисовании.
А контролы не обязаны требовать вьюмодель для хранения чего то.
А если у тебя вьюмодель ВНУТРИ контрола, то это уже не вьюмодель из MVVM (где по правилам нужно отделять мух от котлет), а стейт - где нет никаких ограничений ибо это все относится к виду (и то что это INPC - не делают его не видом)
Потому я упомянул вьюмодели в разрезе MVVM - вот им про вид знать нельзя, а стейтам можно конечно.
>"Appearance" это один из разделов настроек, в котором хранятся и кисти, и размер шрифта и название шрифта.
да какая разница. главное что вьюмодель не содержит в себе части вида.
то есть в настройках у тебя будет AppearanceViewModel где у тебя будет свойство цвет #fafafa и конвертер, а не объект Brush
название шрифта и конвертер, а не сам шрифт
Если нет, то где можно, чтоб, как в винформах, программировать мышкой и изображения легко получать через copyfromscren?
Можно было компилировать WinForms приложения под Linux. Чем проще приложение, тем лучше оно работало. Нынче Майкрософт похоронила Mono. Т.ч. ты ещё заебёшся искать старый Monodevelop и библиотеки.
И в Monodevelop не было редактора форм. Создавать и редактировать формы придётся в Visual Studio.
>ага, информацию. но не саму кривую.
Да понятно, но вот за это я MVVM и не люблю. Казалось бы у тебя уже есть объект кривой с данными: имя, трансформации, стиль контура, стиль заливки. Но ты должен создать модели с аналогичными свойствами по суди дублируя всю библиотеку. А там только для одного стиля контура кривой ебнешься сколько параметров: контур сплошной или пунктирный, какой формы будет наконечник кривой, каким образом будут стыковаться сегменты, какая толщина кривой, какая у нее кисть. Десятки параметров. Сами кисти тоже имеют кучу свойств. Вроде уже есть готовые структуры Matrix, Point, но ты должен написать свои аналоги.
И я уже молчу, что во многих классах систем виндовс внутри находится логика. Например поиск габаритного контейнера выделенных кривых.
Т.е. я должен написать свой собственный метод, потому что мы должны быть готовы отделить вью от вьюмодели.
Это пиздец. Это натурально перелопачивать всю систем виндовс.
>И то не факт.
Если мы говорим о графическом редакторе, то там интерфейс пронизан данными о кривых (пикрил). Это не может не проходить через вьюмродель.
1920x1080, 1:14
MAUI, Avalonia. Первый от майкрософт, второй сторонний.
По идее на всех можно мышкой сверстать интерфейс.
Сам я ими не пользовался, но если они как WPF, то там тоже есть список UI-элементов, которые ты можешь перетаскивать на окно мышкой и компоновать, есть окно свойств. Собсно я когда с формсов переходил на WPF, первый месяц так и делал.
Вроде как тут обычно топят за Avalonia, но она не идет из коробки.
>но вот за это я MVVM и не люблю
это не проблема MVVM. Это ты пытаешься впихнуть все в MVVM зачем то и использовать их как хранилище состояния.
MVVM он служит для того чтобы быть отделенным от вида, а если он у тебя привязан к нему, то это стейт в виде.
>Это не может не проходить через вьюмродель.
может. весь твой редактор может быть выполнен как угодно и наружу выставлять мизер.
отделяй мух от котлет.
у тебя не вьюмодели из MVVM, а стейт твоего редактора.
Почему так? Зачем шарпухи насрали себе в шаровары своими асинк/эвейтами, что теперь невозможно как-либо выйти из ситуации, потому что кодовая база любого проекта засрана ими? Почему белые разрабы джавы оказались умнее индусов майкрософта и просто элегантно ввели гринтреды без каких-либо поломок и изменений в коде?
Написано же, что таски с эвейтами быстрее, чем грин треды.
Ты лучше конкретно напиши действие какого оператора или что конкретно ты не понял. Т.к. с логики любого кто уже разбирается в коде там все элементарно и трудно будет посоветовать какой-то конкретный источник.
угу, это метафора - хранящееся состояние.
Вот делаешь ты сложный контрол и можешь хранить состояние в code-behind, но это может быть сложно или лапша и вообще у тебя там много вложенных контролов. И ты начинаешь делать классы для хранения состояния. И в итоге (но не факт, просто тебе может быть так привычно) у тебя получается иерархия которая похожа кодом на вьюмодели из MVVM как близнецы (и даже имеет окончания VIewModel и навигацию и т.д.).
Только семантика другая - хранить состояние, а поэтому можно завязываться на вид, а также не являются прослойкой между видом и моделью.
вьюмодели тоже стейт же.
Вон в мобилах ты повернул экран и вид пересоздался, а вьюмодель осталась прежняя и сохранила стейт.
Не нужно все пихать во вьюмодели приложения. Не все дружелюбно ко вьюмоделям. И потому вьюмодель приложения из MVVM не должна хранить кишки. Она хранит свой стейт
берем, допустим, AvalonEdit как сложный редактор. Вьюмодель будет содержать string Text {get; set;}, разные команды, высокоуровневые абстракции. А все хранение текста на низком уровне и работа с ним - будет в AvalonEdit. И при смене состояния AvalonEdit через code-behind будет изменено состояние вьюмодели.
Вот пилишь ты свой редактор. Он не кросс. Ты сделал то, что ты вьюмоделями называешь с кистями и линиями. А потом тебе задача - дополнительно на линуксах пусть рисует через GTK (а на винде WPF). И весь твой код хранящий линии тебе придется дублировать. И получается что хранить тебе нужно не линии и кисти, а данные и прослойка которая отделяет тебя от движка рисования.
ну да лишняя работа, но тут 2 стула - либо ты сидишь на одном и "ничего лишнего не нужно будет" или же ты абстрагируешься как то.
Так что внутри контрола у тебя может быть "свой MVVM", но из-за нарушений правил я предпочитаю называть его стейтом. Ну а если правила не нарушать (не хранить кисти например), то тогда да - оно MVVM внутри контрола.
Так что может ты и делаешь этот MVVM внутри контрола, но я то откуда знаю. Я пишу приложения, а в контролах мне такого не требуется. Контрол это вообще низкоуровневый код может быть но и его достаточно.
угу, это метафора - хранящееся состояние.
Вот делаешь ты сложный контрол и можешь хранить состояние в code-behind, но это может быть сложно или лапша и вообще у тебя там много вложенных контролов. И ты начинаешь делать классы для хранения состояния. И в итоге (но не факт, просто тебе может быть так привычно) у тебя получается иерархия которая похожа кодом на вьюмодели из MVVM как близнецы (и даже имеет окончания VIewModel и навигацию и т.д.).
Только семантика другая - хранить состояние, а поэтому можно завязываться на вид, а также не являются прослойкой между видом и моделью.
вьюмодели тоже стейт же.
Вон в мобилах ты повернул экран и вид пересоздался, а вьюмодель осталась прежняя и сохранила стейт.
Не нужно все пихать во вьюмодели приложения. Не все дружелюбно ко вьюмоделям. И потому вьюмодель приложения из MVVM не должна хранить кишки. Она хранит свой стейт
берем, допустим, AvalonEdit как сложный редактор. Вьюмодель будет содержать string Text {get; set;}, разные команды, высокоуровневые абстракции. А все хранение текста на низком уровне и работа с ним - будет в AvalonEdit. И при смене состояния AvalonEdit через code-behind будет изменено состояние вьюмодели.
Вот пилишь ты свой редактор. Он не кросс. Ты сделал то, что ты вьюмоделями называешь с кистями и линиями. А потом тебе задача - дополнительно на линуксах пусть рисует через GTK (а на винде WPF). И весь твой код хранящий линии тебе придется дублировать. И получается что хранить тебе нужно не линии и кисти, а данные и прослойка которая отделяет тебя от движка рисования.
ну да лишняя работа, но тут 2 стула - либо ты сидишь на одном и "ничего лишнего не нужно будет" или же ты абстрагируешься как то.
Так что внутри контрола у тебя может быть "свой MVVM", но из-за нарушений правил я предпочитаю называть его стейтом. Ну а если правила не нарушать (не хранить кисти например), то тогда да - оно MVVM внутри контрола.
Так что может ты и делаешь этот MVVM внутри контрола, но я то откуда знаю. Я пишу приложения, а в контролах мне такого не требуется. Контрол это вообще низкоуровневый код может быть но и его достаточно.
MMVM, конечно, кривое говно из жопы индуса, но тут ты не прав. Бизнес-логика - это одно, presentation layer - совсем другое. Ок, сегодня у тебя вью повторяет все свойства структуры Point, завтра понадобится показать новое свойство и ты соснешь.
Рассматривай MVVM как классическую MVC, в которой дебилы из микрософт объединили модель и контроллер в одну неведомую хуйню. Ты пишешь контроллер, который не возвращает джейсон, а устанавливает сам себе свойства.
индусища...
Для вас говноедов уже отдельный загончик завели: https://2ch.hk/pr/res/2973076.html (М) . Так что не засирай тред, съеби в загончик и варитесь там в говне с такими же любителями со всех сторон барикад. Мешаешь уважаемым людям WPF обсуждать.
Я не совсем понимаю зачем делать столбцы невидимыми. Контрол только отображает данные, либо их редактирует. Скрыв столбец, ты избавляешься от первого и второго. Так зачем этот столбец учитывать в таблице?
Если твоя таблица строит столбцы автоматом и столбец id появляется сам собой, то ты можешь для своего датагрида сделать DataTemplate и указать те столбцы, которые тебе нужны.
Там на самом деле куча темплейтов и под заголовки и под группы.
Если ты контрол со столбцом id используешь для привязки другого контрола, то так тоже не делают. Обычно привязываются напрямую к дата контексту. Если эти данные надо как-то интерпретировать или объединить с другими данными, то используют ValueConverter (может это называли адаптером?)
всего то через 13 лет как первопроходец шарп задал эту тему (которую потом стащили куча языков к себе)
Умные разрабы жавы ЛОООЛ. 13 лет думали умные
и бесконечное число лет будут делать гетсет искаропки
уйди говноед.
У меня есть кнопки для редактирования строк таблицы.
Заранее говорю что смотрю по Авалонии.
Почему раздумаю: в SO пишется что обработчики (Events) гораздо лучше чем команды (Commands) т.к. меньше бойлерплейта.
Но в отличие от команд я не понимаю как в обработчиках передать id без его скрытия в таблице в условно невидимом столбце, видимо EventHandler перегружать надо, и тогда только смогу напрямую прокинуть в DeleteHint сам ID, без мудрения с родительскими контролами и невидимостью.
Есть первый вариант для кнопок изменения/удаления (команды):
Использовать команды для этих кнопок (сами столбцы в TreeDataGrid в XAML нормально не сделать, в примерах только через создание FlatTreeDataGridSource)
Source = new FlatTreeDataGridSource<Hint>(Hints)
{
Columns =
{
new TextColumn<Hint, string>("Text", x => x.HintText, (r, v) => r.HintText = v, options: EditOptions),
new TextColumn<Hint, string>("Comment", x => x.Comment, (r, v) => r.Comment = v, options: EditOptions),
new TemplateColumn<Hint>("", new FuncDataTemplate<Hint>((a, e) => DeleteButtonInit(a.Id), supportsRecycling: true)) //тут перекидываем id в кнопку, DeleteButtonInit создает кнопку
},
};
public Button DeleteButtonInit(int id) //создание кнопки с командой для удаления
{
Button btn = new Button();
btn.Content = "Delete";
btn.Command = DeleteHintCommand;
btn.CommandParameter = id;
return btn;
}
public void DeleteHint(int id) //само удаление
{
var removed = new Hint(id);
using (var DataSource = new HelpContext())
{
DataSource.Hints.Attach(removed);
DataSource.Hints.Remove(removed);
DataSource.SaveChanges();
}
Hints.Remove(removed);
}
Второй вариант - event
будет создаваться столбец с небольшим отличием от кода первого варианта
new TemplateColumn<Hint>("", new FuncDataTemplate<Hint>((a, e) => DeleteButtonInit(), supportsRecycling: true))
public Button DeleteButtonInit() //создание кнопки с обработчиком для удаления
{
Button btn = new Button();
btn.Content = "Delete";
btn.Click += DeleteHint;
}
private void DeleteHint(object sender, RoutedEventArgs e) //сам обработчик
{
Button btn = (Button)sender;
var id = btn.Parent.Parent[0]; //тут еще не до конца разобрался как невидимый столбец подцепить, но вкратце его можно выцепить через родителоьский контрол (для этого и невидимость)
var removed = new Hint(id);
using (var DataSource = new HelpContext())
{
DataSource.Hints.Attach(removed);
DataSource.Hints.Remove(removed);
DataSource.SaveChanges();
}
Hints.Remove(removed);
}
У меня есть кнопки для редактирования строк таблицы.
Заранее говорю что смотрю по Авалонии.
Почему раздумаю: в SO пишется что обработчики (Events) гораздо лучше чем команды (Commands) т.к. меньше бойлерплейта.
Но в отличие от команд я не понимаю как в обработчиках передать id без его скрытия в таблице в условно невидимом столбце, видимо EventHandler перегружать надо, и тогда только смогу напрямую прокинуть в DeleteHint сам ID, без мудрения с родительскими контролами и невидимостью.
Есть первый вариант для кнопок изменения/удаления (команды):
Использовать команды для этих кнопок (сами столбцы в TreeDataGrid в XAML нормально не сделать, в примерах только через создание FlatTreeDataGridSource)
Source = new FlatTreeDataGridSource<Hint>(Hints)
{
Columns =
{
new TextColumn<Hint, string>("Text", x => x.HintText, (r, v) => r.HintText = v, options: EditOptions),
new TextColumn<Hint, string>("Comment", x => x.Comment, (r, v) => r.Comment = v, options: EditOptions),
new TemplateColumn<Hint>("", new FuncDataTemplate<Hint>((a, e) => DeleteButtonInit(a.Id), supportsRecycling: true)) //тут перекидываем id в кнопку, DeleteButtonInit создает кнопку
},
};
public Button DeleteButtonInit(int id) //создание кнопки с командой для удаления
{
Button btn = new Button();
btn.Content = "Delete";
btn.Command = DeleteHintCommand;
btn.CommandParameter = id;
return btn;
}
public void DeleteHint(int id) //само удаление
{
var removed = new Hint(id);
using (var DataSource = new HelpContext())
{
DataSource.Hints.Attach(removed);
DataSource.Hints.Remove(removed);
DataSource.SaveChanges();
}
Hints.Remove(removed);
}
Второй вариант - event
будет создаваться столбец с небольшим отличием от кода первого варианта
new TemplateColumn<Hint>("", new FuncDataTemplate<Hint>((a, e) => DeleteButtonInit(), supportsRecycling: true))
public Button DeleteButtonInit() //создание кнопки с обработчиком для удаления
{
Button btn = new Button();
btn.Content = "Delete";
btn.Click += DeleteHint;
}
private void DeleteHint(object sender, RoutedEventArgs e) //сам обработчик
{
Button btn = (Button)sender;
var id = btn.Parent.Parent[0]; //тут еще не до конца разобрался как невидимый столбец подцепить, но вкратце его можно выцепить через родителоьский контрол (для этого и невидимость)
var removed = new Hint(id);
using (var DataSource = new HelpContext())
{
DataSource.Hints.Attach(removed);
DataSource.Hints.Remove(removed);
DataSource.SaveChanges();
}
Hints.Remove(removed);
}
Значит, что я попробовал варианты ответов и ничего существенно не поменялось. Ответ такой же, разве что builder.Services.AddControllers().AddJsonOptions(options =>
options.AllowInputFormatterExceptionMessages = false);
немного меняет вывод "$.Id". Потрогать хочу, чтобы изменить вывод ошибки. Типо "Вы не ввели такое-то значение" и т.д.
1. проблема формата, если так нужно самому какую то логику делать то и мапь сам из string? с какими угодно ошибками
2. на фронте должны быть все ошибки заранее выкинуты и запрос даже отправлен не должен быть
Это понятно, я когда фронт буду делать все проверки реализую. Но что если кто-нибудь захочет с постмана отправить, так сказать во вред или чисто из интереса посмотреть, что будет
То и будет. Ошибка абсолютно понятная которую только именно что васян подпивас не поймёт
Хмм. Понял, тогда так и оставлю. Просто я думал, что выносить наружу такие ошибки не очень, поэтому и хотел переписать вывод ошибки
Никто не качает оракловую ждк. Подводные высосаны из пальца теоретиками, которые дрочат спеки вместо написания кода.
Это один из самых бесполезных бенчмарков из всех существующих, потому что в реальном мире никто никогда так код не пишет, потому что это совершенно невозможно поддерживать.
А какое отношение твой долбоебизм имеет к теме?
Подскажите быструю и простую key-value базу на шарпе, с открытым кодом.
Я больше чем уверен, ты только сегодня узнал, что вообще есть коммерческая ждк и есть где-то какая-то попенсорсная.
private int privateData;
или
private int _privateData;
Пишу так как сами майки пишут аспнет кор, да и большинство вокруг кроме отбитышей так пишут
Спб, а можно ссылку на кодстайл, меня чет гугл унизил.
Просто так повелось в винформах
Ну и в целом иногда обработчики событий так неймят
Ты видел, какой там код? Это пиздец, там такие лоулевел микрооптимизации, что страшно становится.
Ну и это изначально конкурс жабадебильных олимпиадников, кто задрочится сильнее, а не сравнение производительности платформ.
Чтобы сравнить джаву и дотнет, надо написать сначала наивные реализации с построчным чтением, складыванием в обычные словари/хэшмэпы и вычислением результата. Оно, конечно, будет очень медленно работать, но зато будет видно, как платформы справляются с обычным кодом.
Потом можно попробовать очевидные оптимизации типа буферного чтения по мегабайту и вычисления среднего/мин/макс на ходу без загрузки всего в память.
На этом, в принципе, можно и закончить.
Все остальные оптимизации надо просто писать на С.
а потом пришли primary конструкторы и послали в жопу кодстайлы )
Винформы просто генерируют имена обработчиков по имени объекта на форме, который эмитит это событие.
Нормальная конвенция по именам:
с префиксом _ - все приватные поля.
все методы - в PascalCase
переменные - в camelCase
Это особенность вижуалстудии. Винформы сами по себе ничего не генерируют, обработчик события можно назвать хоть капсом.
Это я рукожоп, баг в докере или теперь при конфигурации учитывается launchsettings, который всегда раньше нужен был для IDEшек?
>Но в отличие от команд я не понимаю как в обработчиках передать id без его скрытия в таблице в
id должен находиться в модели. Целевая модель должна находиться в списке выбранного во вьюмодели.
Событие\команда обращаются к дата контексту, где лежит твоя вьюмодель, обращается к выбранным элементам и получает их id. В идеале так. И не важно событие у тебя или команда в этом случае.
Еще я бегло посмотрел, а выглядит так, что ты кнопки создаешь не в xaml. Жуть какая. Ты создаешь кнопку при помощи xaml, привязываешь к ней соответствующую команду, а ее Visibility или IsEnabled при помощи ValueConverters определяешь по состоянию того или иного свойства вьюмодели.
Если тебе нужно отображать какой-то блок контролов, то делается это через контент презентер. Все упирается в данные вьюмодели.
Ты рукожоп. Работают сервисы на 8 корке в кубах без проблем с дефолтным 8080 и рутлесс правами
А вообще не понял как ты приплёл проброшенные порты.
Определись в начале где у тебя проблема, в том что кетрел слушает не тот порт или что докер не прокидывает нужный.
docker compose config и docker inspect тебе в руки
Докер прокидывает левый порт, но по идее конфиг приложения определяет какие прокидывать, не?
Приложение поднимается, в логах 8080 в режиме продакшна, в compose 8080:8080, но достучаться до него невозможно. Когда делаю curl до этого порта, то connection refused by peer. При попытке чекнуть порты у контейнера видно, что там прокинут 80 порт на тот, что указан в launchsettings из диапазона 5000-5300. Ощущение, что с докером чёт не так, удалять всё и делать docker builder prune --all пробовал, но результат не даёт. Чекал ещё ASPNETCORE_HTTP_PORTS в переменных контейнера, там тоже 8080, нихуя не понимаю вообще
Блять, запустил на другой тачке в докере всё то же самое, заработало. Хуйня ебаная.
Ты всё свливаешь в одну кучу, учись траблшутить.
В твоём случе путь должен быть примерно таков:
1. чек что внутри контейнера софт слушает порт и отвечает (тем же курлом ВНУТРИ контейнера)
2. чек docker compose config что порты правильно прокинуты
3. запуск docker compose down && docker compose up, чек docker container inspect что всё правильно
4. чек iptables-save, рестарт докер демона
5. рестарт хоста
Здраво звучит, спасибо, анон. Про curl внутри контейнера и docker compose config знаю, по последнему как раз видел, что в compose оказывались порты, которых быть не должно. Решилось в итоге рестартом хоста
> но по идее конфиг приложения определяет какие прокидывать, не?
Для начала - тебе вообще нахуй не нужно прокидывать порты, просто обращайся по имени контейнера сразу на порт контейнера.
Дальше - у тебя есть приложение, которое слушает определённый порт внутри своего контейнера. Есть контейнер, который хуй знает как реализован в твоём сетапе. И есть какая-то машинерия проброса портов, которая опять же на всех операционках реализована и работает по разному (и шансы что-то раздебажить у тебя есть только на линуксе). Так что если хочешь подсказку куда смотреть, скажи операционку и в чём ты запускаешь докер, и мб тебе помогут.
Ну вариантов то не много. Бсд сразу нахуй т.к. там докер через пизду прибит, макось туда же, в винде на сколько знаю то что называется докер десктоп работает внутри всл2, ну и база в виде лини.
Всё сводится к тому что кроме лини вариантов то и нет
> в винде на сколько знаю то что называется докер десктоп работает внутри всл2
С линуксовыми контейнерами. Для виндовых контейнеров никакие вслы, конечно же, не нужны.
Чего это вдруг? Там урезанная довольно быстрая винда.
WSL2 тоже довольно быстрый, кстати. В некоторых тестах даже обгоняет соответствующий линукс. В большинстве, конечно, отстаёт, но в большинстве из этого большинства всего в пределах 10%.
Просто нет причины заниматься извращенствами когда весь прод с ног до головы на лини а в винде для разрабов завезли всл.
Единственные причины держать винду в проде как вижу это лдап/ад и дикие вендор локи
4.7.2 под моно нормально ворочался, а вообще ретрограды должны страдать.
Всего то прошло 6 лет с 2.1 лтсного кора, продолжим насиловать труп фреймворка!
> 4.7.2 под моно нормально ворочался
Я не верю, что он работал хотя бы с 80% скорости дотнета. Плюс какие были гарантии, что он вообще правильно код выполнял?
> Всего то прошло 6 лет с 2.1 лтсного кора
Использовать кор в то время для энтерпрайза было безумием. Там в каждой версии всё менялось, баги, проблемы с производительностью.
Стартап сайта даже в 6 дотнете выглядит не так, как в 7, взяли и перехерачили классы. Это трата времени на апгрейд.
Поэтому никто особо старые проекты с фреймворка не переводит, и хостить их гораздо проще на винде.
Я, собственно, сам новый дотнет только несколько месяцев назад начал использовать, и, конечно, хочу сказать, что стало гораздо лучше, и как хорошо, что громоздкий IIS с проблемами в настройке нахер больше не нужен.
Новые проекты надо делать исключительно на новом дотнете, но легаси-то никуда не девается.
Под виндой часто работают хосты на проде, где нужна какая-нибудь работа с криптографией по госту: в новых дотнетах относительно хуй на расширяемость клали в плане криптографических провайдеров. На гитхабе ишью шесть лет лежит: https://github.com/dotnet/runtime/issues/26053
>Я, собственно, сам новый дотнет только несколько месяцев назад начал использовать
Сочувствую. Я уже года 3 не касался .net framework-a.
Последние полтора года вообще исключительно .net6 и под linux только работаю.
Красота.
Замечание анона выше про упоминание оси справедливое, т.к. запустить контейнер пытался под макосью, потом сдался и с первого раза всё на линуксе запустилось
Я себе плохо представляю, как у дотнет девелопера вообще может появиться задача запустить контейнер докера под макосью.
Ну хер знает, у меня примерно пятая часть знакомых .net разрабов работают на маках. Но честно говоря, не интересовался ни разу была ли у них необходимость возиться с докером.
Но ведь vs под винду только? В чём они пишут, vs code? Оно же гораздо менее функциональное.
Джетовская идешка жи ест. Но мне она не по душе, хоть и вебшторм топчик и в студии стоит решарпер
>В чём они пишут
В основном в райдере. VS под мак вроде как бы и существует, но майрософт сказали, что 24 августа 2024 забьют хер на неё.
VS под мак - это MonoDevelop.
И MonoDevelop - была вполне нормальной ИДЕ для тех задач, под которые оно пилилось.
Весь вуз сидел на ней и горя не знал.
Нет. В вузе я был нетакусиком, и на линуксе сидел, чтобы выебываться перед однокурсниками. А в то время - еще core не было и vscode тоже. Так что делал лабы на Mono и соответственно в MonoDevelop.
Ха, ты мне напомнил, как у нас линуксоиды делали лабы по ТБД на MySQL, а потом они у них в универе не запускались.
Не смотри
Меня тоже корёжит. Изначально девы в мс тоже не использовали их в пику конвенциям, ну и я привык просто с маленькой буквы поля называть.
А потом им, видимо, вставили за это, поэтому пришлось делать по конвенциям.
Алсо, вот вам референс.
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/identifier-names
Меня гораздо сильнее корёжит когда код засран кучей this.
и нужно именно так сеттер написать, чтобы не копипасть кучу строк кода которые делаются в Set вьювмодели
Как исправить ошибку?
>Вот упростил... то есть проблема в передаче ссылки (в с++ такое работает, а как тут надо?)
Тебе же писали уже - выкидывай нахрен эти плюсовые приколы, в шарпе не пишут так.
>Как исправить ошибку?
Забыть плюсы и прочитать учебник/справочник по шарпам.
то что это мне надо сообщить что поле изменилось вызвав OnPropertyChanged
А как мне переписать Set из >>24747
чтобы оно работало?
В модели DataModel не должно быть функционала вьювмодели.
Не копипастить же поля из модели DataModel в вьювмодель DataVM - говнокод же, когда одно и тоже в разных местах
Поэтому сделал что DataVM хранит весь DataModel
Но теперь надо написать поля которые будут доступны вьюву.
Конечно же можно написать как тут предложили >>24791
Но в таком случае не будет обработки события и вьюв не будет знать что где-то что-то поменялось. Тоже хуита
В таком случае опять приходим к копипасту - когда нужно вот эти 4 строки из Set писать в сеттеры - это же пиздец копипаста сколько, если полей 10, то это 40 строк говна сверху.
так что логично что нужно вызвать из сеттера метод который изменит поле DataModel
>Не копипастить же поля из модели DataModel в вьювмодель DataVM - говнокод же, когда одно и тоже в разных местах
>
>Поэтому сделал что DataVM хранит весь DataModel
Ну т.е. ты пытаешься заменить говнокод с простым дублированием, на говнокод с хер пойми какой логикой. Такое себе.
ну у меня сейчас получилось что модели наследуются от вьювмодели - это же неправильно.
начал искать как другие делают - а они копипастят
public string Id {
get => _model.Id;
set {
if (Equals(_model.Id, value)) return;
_model.Id = value;
OnPropertyChanged(nameof(_model.Id));
} }
Хотел избавится от этого говна с помощью такой функции - это же логично что копипаст надо скрывать. Да и ошибок меньше - тут надо же три места изменить после копипаста - а если не изменю (обычное явление при копипасте)?
Всего 3 основных фреймворка. То ли дело майки с wpf, uwp, winui, maui, xamarin и тд. А жс прекрасный язык для ui. Постоянно совершенствуется. Когда там xaml обновлялся? Точно, в 2006 году. Хотели еще в 2009 новый стандарт выпустить, но так и не разродились, ресурсов не хватило, лол. Маленькая бедная компания, хуле, не смогли даже завести поддержку дженериков в xaml.
>ага, небось пошел во фронтенд )
Не, чистый бекенд.
В начале карьеры немного замазался об реакт, но сейчас только бэк и ни шагу дальше API.
хамарин вообще не десктоп
мауи это десктоп для хамаринистов
UWP не нужен
>жс прекрасный язык для ui
в каком месте? могут быть норм фреймворки в рамках которого ты пишешь код и все выглядит неплохо, но сам жс как язык настолько хорош, что породил кучу альтернатив лишь бы на жс не писать. Тот же тайпскрипт один из кучи )
>Когда там xaml обновлялся
есть такое. Я бы хотел подобие jetpack compose, но шарп не котлин и можно лишь подобие combine ui
однако jetpack desktop показывает что не все так радужно
так что пока что хамл
>даже завести поддержку дженериков в xaml
не знаю как вы пишете. ни разу это не понадобилось.
вот со словарями они говно сделали да.
>>25642
у каждого свои радости. в десктоп софте не нужно заморачиваться над многими вещами типа безопасности и скалируемости.
>интереснее разработки под дескоп
что там интереснее - очередной говносайт для семь топоров клепать?
Можно ли исправить не пересоздавая проект?
>Меняешь тип проекта в первой строчке цспроджа
Одно и то же. Разница только в строке
<UseWPF>true</UseWPF>
Но она ничего не решает.
>Добавляешь платформу в референсы
Где? Я ничего не вижу. Платформа это целая группа библиотек.
Молодец.
>>26163
лан, один хрен проекты почему-то несовместимы.
В одном проекте платформа
Microsoft.NETCore.App
А в другом две
Microsoft.NETCore.App
Microsoft.WindowsDesktop.App.WPF
Так вот первый ругается, если в качестве референса указать второй проект. Я же не какой-то НетФреймворк подключаю, или пониженную версию.
В проекте, который используется переименованный, выдаёт ошибку
Не удаётся преобразовать из "{namespace}.{class}" в {class}
Название проекта - дело важное. Незазорно просидеть пару часов, придумывая правильное название, прежде чем нажать "создать" в IDE. Если у тебя возникает необходимость его переименовывать после создания - значит плох ты как программист.
Забейте, оказалось, что кто-то не я выставил заполнение некоторых полей прямо в сеттерах у этого объекта. Я уже думал, что у меня крыша едет.
Майкрософт, залогинься
Смотрите какую хуйю придумал чтобы наебать EFCore
Собственно. У меня была проблема. Есть сущность:
public class User{
public int Id { get; set; }
public int AppIdentificator { get;set; }
...
}
Собственно. Этот AppIdentificator по бизнес-логике, надо при удалении пользователя - переиспользовать. Типа - было 4 пользователя. Второго удалили. При добавлении нового - надо дать ему освободившийся.
И я долго ломал голову. КАК, блядь, сделать, чтобы оно работало с нормальной скоростью.
И в общем. Че я сегодня придумал.
ДОБАВИТЬ КЛАСС.
publc class AppIdentificator{
public int Id {get; set;}
public int? UserId {get; set;}
public User? User {get; set;}
}
И тогда - проблема решается оче просто.
Я просто беру, и ищу в этой таблице - первый незанятый. Если не нахожу - создаю новый.
Работает, судя по тестам - быстрее, чем ебанутый код, который был для поиска дырок.
Но теперь меня мучают сомнения. Ну не может же все быть так хорошо. Я 100% чет не учел. Может раскритикуете решение?
Нативные запросы - все еще быстрее, даже с учетом старой структуры, но мне на работе не разрешают писать нативные запросы, говорят, что не по понятиям это все дело, и надо с EF ебаться.
Смотрите какую хуйю придумал чтобы наебать EFCore
Собственно. У меня была проблема. Есть сущность:
public class User{
public int Id { get; set; }
public int AppIdentificator { get;set; }
...
}
Собственно. Этот AppIdentificator по бизнес-логике, надо при удалении пользователя - переиспользовать. Типа - было 4 пользователя. Второго удалили. При добавлении нового - надо дать ему освободившийся.
И я долго ломал голову. КАК, блядь, сделать, чтобы оно работало с нормальной скоростью.
И в общем. Че я сегодня придумал.
ДОБАВИТЬ КЛАСС.
publc class AppIdentificator{
public int Id {get; set;}
public int? UserId {get; set;}
public User? User {get; set;}
}
И тогда - проблема решается оче просто.
Я просто беру, и ищу в этой таблице - первый незанятый. Если не нахожу - создаю новый.
Работает, судя по тестам - быстрее, чем ебанутый код, который был для поиска дырок.
Но теперь меня мучают сомнения. Ну не может же все быть так хорошо. Я 100% чет не учел. Может раскритикуете решение?
Нативные запросы - все еще быстрее, даже с учетом старой структуры, но мне на работе не разрешают писать нативные запросы, говорят, что не по понятиям это все дело, и надо с EF ебаться.
Я бы сказал что ты вывернул наизнанку.
Моё решение такое т.к. удалять юзеров из бд не принято (из опыта)
>int?
Не затрахивает потом каждый раз на налл проверять или писать "?." где вместо падения происходит заглушение и игнорирования проблемы?
Я правда не понимаю эту победу над null, ведь когда пишем чуть больше кода чем скрипт, это дико становиться неудобным.
Не понимаю претензию. Наллабл типы имеют свои фичи и ясен пень их не нужно тащить туда где они не нужны и предполагается что весь спектр значений валиден. Это с условынм DateTimeOffset почти всегда можно сравнение делать с default. И в целом Nullable<> это прямое указание что "тут может быть налл"
Ну если ты уверен, что код проверен, то ставишь ! и всего делов.
Где проверен, так может быть распроверен. Как бы не иммутабельное.
В итоге количество "заткнись!" сильно меньше проблем NRE в рантайме.
>[сообщение внутри скобок] сообщение справа от скобок
К примеру выражение '\](.*)' вернет такой кусок:
'] сообщение справа от скобок'
А мне нужно
'сообщение справа от скобок'
Ты должен брать не заматченый текст целиком а первую группу то бишь то что внутри первого (). Кури доку
(?<=\]\s)(.*)
>Ты должен брать не заматченый текст целиком а первую группу то бишь то что внутри первого ()
Ничего не понял.
https://habr.com/ru/articles/545150/
Позитивный просмотр назад '(?<=шаблон)'. Сдвигается вперед на указанный шаблон. Т.е. '(?<=\])' вернет результат:
>' сообщение справа от скобок'
Остается пробел, поэтому '(?<=\]\s)'
https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.match.groups?view=net-8.0
Не представляешь как я хотел хуями обложить
Ты про это? Я тестировал на онлайн площадках и не знал, что так можно. Спасибо.
Алсо, полезно знать, что фичи регулярок практически одинаковые во всех языках, и те же группы есть везде. Особенно это полезно при find & replace.
Используется так, например (развернуть присваивание):
Find: ([^=]+)\s☆=\s☆(.+?)$
Replace: $2 = $1
Всего групп может быть 9, $0 - это вся заматченная строка.
Звёздочку заменить на
>Ну если ты уверен, что код проверен, то ставишь ! и всего делов.
Лол я думал не стали завозить синтаксис "!.", но тоже такое себе по красоте.
> Как только ты ставишь вопросик, так начинается ебля с этим полем по всему коду, хотя где-то там в коде он был уже проверен.
Так ты не прокидывай один класс через разные слои абстракций, а на каждое взаимодействие между слоями пиши свой класс. Да, они будут на 90% одинаковые, и время тоже на это уходит, зато потом нет вопросов типа "почему половина полей приходят пустые?" или "почему это поле из тела пост-запроса не сохраняется в базу?"
Это просто будет гига-зоопарк одних и тех же сущностей. Тут наверное проще ! пописать.
Хотя ладно, я тупо отключил нуллабельность. Логи покажут где я насрал.
> Это просто будет гига-зоопарк одних и тех же сущностей.
Они как правило не одни и те же, а чуть-чуть разные. Тебе, чтобы использовать не до конца подходящую сущность, придётся писать костыли. Конечно очень легко в самом начале разработки, когда ты просто достал сущность из базы и переслал её на фронтенд, но с каждым таском что-то будет меняться, и этих костылей будет всё больше и больше.
Вон, там в php-треде у кого-то был специальный метод RemoveUnnecessaryFields. Могу ещё легко представить флаг в объекте типа AlreadyProcessedByPriceTransformer.
Это будет сплошным источником багов и неправильного понимания контрактов, и придётся постоянно весь код перечитывать, чтобы было ясно, как оно работает, и что где лежит.
Надо через не хочу сразу клепать эти классы, потому что потом всё равно придётся это делать, только это займёт куда больше времени и сама замена породит ещё баги.
Помню в далеком 2006 кодил под Invision Power Board и офигивал, что они там прокидывали один и тот же мега-ассоциативный массив с тонной вложений.
Зато было удобно кодить, выводишь этот массив и тебе все состояния и данные. Добавляешь данные и они у тебя из всех щелей доступно. Приходилось, конечно, isset'ом проверять, но никогда это не вываливалось проблем.
>но с каждым таском что-то будет меняться, и этих костылей будет всё больше и больше.
Кодинг и так напоминает бесконечное перекладывание данных туда сюда, а ты еще хочешь помножить этот ад.
Для этого придумали мапперы.
> где вместо падения происходит заглушение и игнорирования проблемы?
Не мои проблемы, пусть разбираются те, кто допустил попадание на мой участок null. А если будет падать, то виноват уже я буду
А что если я хочу распарсить файл целиком? Размер строки позволяет загрузить 2Gb, но не лучше ли файл читать построчно? Тогда нужен метод Regex.Match и в этом случае не смогу все это собрать в MatchCollection.
>Алсо, полезно знать, что фичи регулярок практически одинаковые во всех языках, и те же группы есть везде.
Ну я ради тестов открыл сайт, типа https://regextester.github.io, чтобы сразу получать ответ без компиляции программы, но на подобных сайтах не распознаются группы и именования групп, типа '?<myGroup>'.
Регулярки работают с целой строкой.
Круто! Есть подсветка синтаксиса и даже развернутое объяснение что и в каком порядке делается.
Golang is a web scale language.
По скорости разработки самый быстрый тупескрипт, поэтому он дико популярный в штатах. По скорости перекладывания джейсона все эти языки одинаковы.
Джава - это легаси в банках. Голанг форсит гугл, хотя сам язык говно. Шарп как язык заебись, но есть нюанс. Микрософт так сильно форсили шарп как язык для домохозяек, что теперь большой бизнес думает, что на нем только домохозяйки и пишут. Типа, несерьезная технология для мусорных стартапов, которые проще слепить на нодежс. Скажи спасибо дебилам менеджерам, загнали дотнет на парашу.
Ну. Типа допустим, мне не лень взять и написать клиент.
Но возникает проблема. 99% проблем - это проблемы связанные со стабильностью сети. Допустим - оператор чудит, а чужие клиенты про это не думают. Да и самому непонятно как мутить приколдесы типа - разрыва и восстановления соединения. Допустим, тут решили. Как тестировать проблемы связанные с особенностями TCP, типа то что тебе может прилетать из-за nodelay - частями. А может - наоборот из-за охуевшей скорости того как чужой клиент серит - прилететь здоровенный TCP-пакет, в котором сразу несколько сообщений и их надо правильно обработать.
А самая непонятная часть, это то что некоторые вещи начинают происходить в проде - через какое-то время + количество обрабатываемых подключений. Вот типа, ставишь на дев - там для тестов висят постоянно 100 клиентов, и годы идут, все как часы. Ставишь клиенту. Он хуярит 100к клиентов в первый же день, у него все ок, через полгода - уже млн клиентов разом, и чет у него ломается, а объяснить не может, типа - жалуются эксплуататоры, те жалуются - что чет медленно. Смотришь, 25% проца всего загружено и 30 гигов оперативки, что не так много для такой нагрузки. Тестишь своим клиентом - да все ок. Подключается чужой клиент - там видишь уже проблемы, но причина - да хуй его знает где она, потому что логи несутся со скоростью что пиздец, и просто понять что где - невозможно.
В общем. Я не знаю. Наверное тупо спрашивать это в шарпотреде, Большая часть-то тырпрайз или десктоп. Но я всю эту хуйню на .NET делаю. И вот просто хочется - прикрутить тестики, чтобы можно было на них погонять сценарии разные, чтобы не ждать отзывов от рассерженных пользователей. Просто как всю эту хуйню таки потестить - я не представляю.
По большей части я хочу поныть.
А в контексте нагрузочное. Ну, я делаю своих клиентов 100к. Все ОК работает. Миллион на своей машине я не могу поднять. Не работать оно начинает с реальными клиентами, которые по 2g через операторов, которые зачем-то рубят канал рандомно при большой нагрузке, а вопросы - ко мне.
А от шарпотреда я хотел наверное каких-то советов, как делать тестирование нормально, чтобы оно приносило пользу. Потому что, ну наделаю я юнит-тестов, наделаю каких-то интеграционных. А через год аптайма на миллион+ клиентов, чет сломается и хуй знает почему.
Я ещё раз повторяю, что это меньшее зло. Это не добро, птички, любовь, это просто не так плохо, как альтернатива.
Если к тебе претензии что оно не работает на Х нагрузке и тебе не дают железо что бы сделать хотя бы Хх1.5 то нихуя тут не сделаешь. Я бы послал нахуй
Во первых на такие случаи у тебя в ТЗ должно быть прописано четкое SLA. Чтобы не было с нихуя ситуаций вроде "у бизнеса неожиданно пришел лям клиентов и все легло". Вернее ситуации, то такие будут, только если у тебя изначально договор был на "100К запросов в день и плюс 5% в месяц", а бизнесу вдруг выше прогнозов привалило, то это проблемы бизнеса.
Во вторых нормальное нагрузочное тестирование - это отдельная статья расходов и этим занимаются отдельные люди. Т.е. это даже не обычные тестеры, а специальные по нагрузке. У них для этого есть необходимые навыки, чтобы поднимать нужные стенды, вешать на них нормальный мониторинг, писать утилиты, пускать зонды и т.д. Это немалые такие бабки.
У нас к примеру на команду из 5-х разрабов и 2-х обычных тестеров, есть отдельные два тестера по нагрузке (с з.п. не меньше сеньорных разрабов) у которых свой отдельный кластер (уровня прода), на котором они постоянно гоняют разные профили нагрузки.
В соло ты такое не потянешь, это не то же самое как юнит тесты на сервис накидать, это по сути тебе новую профессию освоить нужно.
Поэтому всегда договаривайся с заказчиком на определенный уровень SLA в котором ты на 150% уверен, что твои разработки его потянут, если ему хочется выше, то пусть закладывает в бюджет расходы на нормальное НТ (это где-то от 50% до 100%) и нанимает (ну или ты сам нанимай) нагрузочников.
Ну и еще учись писать масштабируемые сервисы, чтобы в случае чего, можно просто было докупить железа и ебануть больше инстансов.
Разработка масштабируемой отказоустойчивой системы стоит много денег, это задача уровня гугл. Требуй от кабана стенд для нагрузочного тестирования, где будет крутится лям пользователей, а не сто инвалидов на виртуалке. Заниматся тестированием должен отдельный чел, а не ты. Хайперфоманс - это вообще сложная тема, а не просто пукнул микросервисом в докер и дальше оно как-то само.
Для этого есть специальные средства для анализа логов. Есть datadog https://www.datadoghq.com/product/log-management/ есть coralogix https://coralogix.com/ Есть logz.io https://logz.io/, SumoLogic, Splunk. Инструменты для трейсинга там хорошие, можно видеть какой конкретно сервис и url тормозит, все вызовы с таймингами. Можно с помощью машинного обучения детектить атаки.
Насчёт тестов - есть так называемый chaos engineering, где можно тестировать разные сценарии https://github.com/Polly-Contrib/Simmy
В целом, большинство твоих проблем из-за низкого уровня автоматизации. Если у тебя всё ручками управляется, а не скриптами, приходится коннектиться и вручную проверять - то это пиздец. Как бороться с проблемами сети? Да никак нахуй! Тебя вообще не должна ебать сеть. Стабильностью сети должен заниматься cloud provider, который предоставляет услуги. Это его задача защищать от ddos-атак, от всяких syn-flood'ов, ping-flood'ов, udp-flood'ов и прочего.
Ты не можешь купить готовый, managed service? Который будет автоматически масштабироваться под нагрузку. Ну и ебись тогда с сетью. Сделай свой собственный дата-центр ёпт.
Программист вообще не должен этим заниматься. Нахуй вы тогда платите хостинг-провайдеру, скажи мне? Если тебе приходится настолько мелкую хуйню как "клиенты с 2G-интернетом" исправлять, то у меня для тебя плохие новости. Либо твой хостер - мудак, либо ты.
Я знаю, но тебе нихуя не скажу)
Microsoft намерена переписать с использованием языка Rust ключевые сервисы Microsoft 365, изначально написанные на языке C#
Что не так с сишарпом?
Он медленный, даже медленнее джавы. То что там кто-то бенчмарки дрочит, так это не сишарп а вставки с указателями на си или плюсах. Вот и получается, что быстрый код - это код на плюсах. А раст лучше плюсов.
>на раст
А вот тут было смешно. Ты предлагаешь с японского байка на самокат пересесть? Причём даже не на электросамокат, а на тот, на котором ты ногой от асфальта отталкиваешься и катишься до момента, покуда ещё раз ногой оттолнёшься.
Какой нахуй Rust?
нет. я предлагаю узнать ответ что не так с си шарпом и так с растом
ответ прост - НИЧЕГО.
обычная оптимизация горячих частей на более быстром, но менее удобном языке. Используется в мире повсеместно и поэтому тупые вопросы "что не так с <язык>" понимающие люди не задают
У тебя надо каждую вторую строчку менять. Например, если добавить какой-то другой атрибут, получишь исключение.
Деврелы раста увидели вакансию на сайте и побежали покупать статью для линковки. Но что-то пошло не так.
Почаны еще макросов не нюхали, наиграются на деньги кабана и дропнут этот легкочитаемый и любимый всеми язык.
самое забавное, на картинках простые функции, что будет когда начнут писать тырпрайз-монстров?
Займись уже делом, зачем прозябаешь на двачах свою юность.
напиши клиент яндекс музыки под линух, сам такой хуйней маюсь
>Что интересного можно написать на авалонии?
Судя то тому, что я вижу у некоторых разработчиков, на Авалонии можно написать всё. Реально кроссплатформенны GUI. Но всё же интерфейс на ней чуть менее отзывчивый, чем на WinForms.
Не особо вникая, не меняя логики
Так вот кто украл гигабайты и мегагерцы.
Вот, например, есть у меня enum с n значений, и каждому значению биективно сопоставлена строка.
Мне надо написать метод, который конвертирует одно в другое, и метод, который конвертирует обратно.
Если писать через свитчи, это дублирование. Если заводить словарь, то его придётся разворачивать, а это убого.
> Если заводить словарь, то его придётся разворачивать,
Если значений много, то быстре словаря ничего нет. И два словаря это решение.
Если значений немного, то вообще похую на реализацию.
Я хочу, чтобы код нормально выглядел, был читаемым и поддерживаемым. Значений около 10, производительность вообще роли не играет, тут любой способ будет достаточно быстрым.
>>30568
Мне это не нравится, потому что строковый код - это не свойство енама.
Я немного конкретизирую задачу, если интересно.
У меня есть две базы данных, в которых хранятся показания счётчиков. Формат хранения в базах разный, и даже имя одного и того же счётчика записаны по-разному.
У меня есть код, который берет название счётчика и трансформирует его в набор атрибутов, которые этот счётчик единственным образом идентифицируют. Один из атрибутов - это как раз перечисление.
Весь результат едет на фронт, где с ним что-то делается.
Соответственно, на фронте есть фильтрация, и поэтому мне надо обратно собирать идентификатор счётчика для каждой базы из этих атрибутов, и соответственно, это перечисление является частью идентификатора, только в закодированном виде.
Я сейчас написал просто 4 свитча, но мне не нравится дублирование сопоставлений.
Заводить словарь dic, а потом из него делать второй dic2 = dic.ToDictionary(x=> x.Value, x => x.Key) я не хочу, потому что это некрасиво.
Крч понял что кнопки прям в гриде будут ужасно выглядеть, тем более их планируются делать больше одной, поэтому решил запилить их в контекстном меню. Но оказалось что TreeDataGrid умеет только при RowSelection доступно свойство SelectedItem, а при CellSelection нет. А выделять в TreeDataGrid целую строку меганеудобно. Теперь хз что делать, гайдов по созданию собственной selection model не нашел, придется ждать когда эту фичу в либу добавят. Бугурт
>Но оказалось что TreeDataGrid только при selection-модели RowSelection может получить свойство SelectedItem, а при CellSelection нет.
Слоуфикс
var myKey = types.FirstOrDefault(x => x.Value == "one").Key;
Вот это тебе не поможет?
Можно отделаться одним словарём, вместо двух.
Наверное надо пояснить за решение.
1. Производительность роли не играет, так что мы на нее забиваем.
2. Чтобы код был поддерживаемым - мы выносим всю эту муру с картами - в конфигурационные файлики. Если не хочешь, чтобы засиралась папка с проектом и не лазили всякие "ПРОДВИНУТЫЕ ПОЛЬЗОВАТЕЛИ" - делаешь файлик embedded.
Ну а далее. У тебя просто карта лежит в файлике. При надобности - ты ее расширяешь. Хочешь - можешь в одном файлике все эти карты хранить. Код при этом - тебе не надо будет менять больше никогда. И маппер такой ты можешь вызвать из любого места своей программулины. Единственное в плане поддержки - это при добавлении необходимости чет еще маппить таким макаром - ты будешь должен регистрировать это дело. Но это не так сложно.
Я бы оставил свич. Свич поймет и джун, и стажер, и вообще кто угодно.
Минус решения - тебе надо при расширении своего enum'а лезть в этот файлик. Но это решаемо.
Да. Это можно оптимизировать, загружая файл один раз и храня словарь этот. В идеале - сделать ленивую загрузку.
Это ничем не лучше разворота словаря.
>>30715
>>30726
Это жесть какой оверкилл. Вероятность изменения енама и кодов у меня на самом деле близка к нулю, поэтому такой код при всей его мощности очень проигрывает в читаемости.
Ладно, всем большое спасибо за советы и потраченное время.
Я просто думал, может это я дурак, каждый раз, когда приходится делать такой двунаправленный матчинг, пишу говнокод, а есть нормальный способ.
>TreeDataGrid
У авалонии есть TreeDataGrid. Вот прямо щас надо запилить такое на WPF, это какой-то пиздец.
Хочу себе лог вьювер запилить с поддержкой вложения. Миллиард этих вьюверов и все какой-то кал.
Может ли VS сделать две (и более) вкладки (окна редактирования) на один файл??
Жесть, спасибо анонче.
>У авалонии есть TreeDataGrid
Так я о нем и писал. моя проблема - неясно как кастомный Selection Model пилить. В целом у меня нет прям супер претензий к держателям репы, в одном из issue ЕМНИП заявлено что это контрол де-факто в альфа стадии
Я вопрос поставить забыл. Я удивлен. В WPF такого нет. Нашел вариант на CodeProject, где используется обычный DataGrid, но там итем представляется как еще один DataGrid.
Все так, пилим десктопы, учим джаву чтобы перейти в нормальную современную разработку...
Ну окей.
Есть tcp-сервер на шарпе.
Есть железки, которые этот сервер обслуживает. Общение через GPRS(2G/3G)
Есть ОПСОС.
С железками, у которых связь 2G - происходит странная магия. После 25к подключенных железок - с ними начинает рандомно пропадать связь.
ОПСОС говорит - все передаю, сервер не отвечает.
На сервере - я вижу, что через какое-то время, от той стороны не приходят данные, и сервер рубит соединение.
В таком вот режиме - где-то 10% железок - рандомно отваливаются.
При этом, если перезагрузить сервер - все подключаются и какое-то время все ок.
И самая страшная магия начинается вот в чем. Я включаю на уровне сокетов KeepAlive, и начинается сущий пиздец - 90% железок отваливаются. При этом, я вижу WireShark'ом, что кипэлайвы отправляются, но никто не отвечает на них.
Собственно. Вопросы-то в том, почему это началось после вот такой красивой цифры: 25к. До 25к - хоть 2g, хоть 4g, хоть что - стабильно все(ну, разрывы бывали, но в районе погрешности, типа 2-3 устройства отваливаюлись, но после 25к - резкий скачек до 10%)?
Почему - это именно с 2g? 3g и выше - нормально работают. Через Ethernet - тоже все ОК, хоть 100к подключений делай.
Почему KeepAlive, только хуже сделал? Причем значительно. Вроде как опсос говорит, что да, мы рубим, если канал неактивен, вот, кипэлайвом немного нагружаем канал, чтобы был активен, но после его включения - тотальный пиздец начался.
И может ли пиздеть опсос? Потому что на другом объекте - заменили симки - и проблемы исчезли.
И я понимаю, что это вопросы не касающиеся шарпов непосредственно. Потому и не хотел их задавать.
Провайдер может пиздеть - это аксиома.
На первой линии поддержки никогда ничем не помогут, на второй линии поддержки - как повезёт.
И вот когда твоё обращение попадёт к инженеру, который шарит, то он или решит проблему, или объяснит в чём дело.
Исходя из из твоего рассказа вероятность ИСТОЧНИКА проблемы на стороне провайдера на порядок-другой выше, чем проблема с твоей стороны.
Но это не означает что с твоей стороны нет проблем - бывает какая-то сущая мелочь, которую не замечаешь, а она всё решает.
Ах да, несколько раз бывало что проблема на моей стороне, но инженер с той стороны настолько крут, что давал подсказку как исправить.
Ах да, keep alive. Так мобильныйровайдер специально может душить, чтобы не резервировал слот в GSM.
На 2g может просто слотов не хватает. Там временное разделение. Погугли gsm timeslot. Тем более на медленном старинном 2g.
дамп пакетов сними и найди косяки что бы с голой жопой не идти в саппорт
Хоть язык и цепляет возможностью дропнуть сборку мусора, но яп несет тонну проблем.
-плохая читаемость кода.
-это чтение на максимум усугубляют макросы.
-множество брошенных васянских либ, ибо язык на живет на хайпе.
-макросная магия нередко не дает даже изучить эти васянские либы, все постижение идет чуть ли не через ишью
-проблемы с асинками.
-в целом если с хеллоувордами все ок, то дальше может столкнуться с косяками дизайна раста, это лафтаймы, это rc (местная сборка мусора) и прочие костыли.
-какое-то неадекватное комьюнити.
-непонятна ниша языка, для ембеддед нужны костылить чтобы писать, для прикладного нужно страдать и медленно разрабатывать, а системное слишком низкая ниша, да из-за наличие готовых либ, си или плюсы выглядят лучше.
-не забываем что языку уже не мало лет, эта стагнация тоже не приносит бонусов, а успешные менеджеры фонда, как-будто больше заинтересованы политикой и хайпом на продукт, чем на самим продуктом.
В общем, я предлагаю не вестись на хайп, а ждать что-то лучшее или хотя бы зрелости от этого самого раста. К примеру, тот же зиг сделал многие вещи из раста намного проще, поэтому варинт что могут высрать более удобный язык под большим финансированием гигантов, все же остается
Я наоборот люблю, когда медленно двигается, к вечеру не нужно портянку бессмысленного флуда читать.
Двачую, раст не нужен. Я прямо сейчас пишу на нем такой себе curl на минималках и это пиздец. Язык максимально душный, документации нихуя, примеры кода устаревшие, после сишарпа будто вернулся во времена перфокарт. Каждый мудак обязательно использует макросы, в итоге ты просто копипастишь куски кода и даже не понимаешь, как это работает. Ваш Result не Result, пришло время написать unwrap, напиши его снова. А вот тут вы передали владение ололо засрите весь код mut ссылками на вашу переменную.
Автор сишарпа и тайпскрипта просто гениальный гений, блять, на фоне этих долбоебов в чулках.
Используй шардинг на несколько симок, чтобы по каждой не превышать лимит в 25к. Разным клиентам выдай разные номера.
>Автор сишарпа и тайпскрипта просто гениальный гений
А то. Особенно если вспомнить, что он еще и создатель Turbo Pascal'я и Delphi. Хейлсберг наше всё.
>тайпскрипта
Оверсложные типы, отсутствие совместимости с дотнет. Сомнительное решение без будущего. Заменяется одним javadoc который не портит читабельность и не требует сопровождение двух языков.
Вообще, в ИТ многое идет не туда. Например отсутствие прокси языка у С++, нет прокси языка у кривого го.
Котлин, который пошел по пути бредовой мультиплатформы, вместо того чтобы стать языком универсалом, который мог бы собираться под рантайм го или рантайм дотнета.
> собираться под рантайм го или рантайм дотнета.
Поясню, чтобы не казалось бредом.
Они реально это обсуждали и допускали на уровне желаний.
Если с го были какие-то проблемы, до дотнет был достижим.
Так все люди изначально создававшие котлин ушли из жб. Я вообще хз зачем он нужен, тот же свифт гораздо любопытнее выглядит, но там ситуация как с шарпом - ряяя эпл вердерлок.
Ты случайно не тот шизик, который все растотреды засрал? Про маркетинг и фанбоев забыл
TurboPascal создал Филипп Кан, а парень, о котором ты говоришь, создал протоип Blue Label Pascal, который перекупил Филипп.
Типа. Допустим. Есть код как на прикриплейд.
Вроде кажется логичным. У нас есть некий базовый абстрактный класс, в котором общая логика. Есть какой-то кусок, который должен отличаться. Делаем метод абстрактным или виртуальным. Потом наследуемся, получаем ништяки базового класса, а остальную часть реализум.
Но вот оказывается, что что-то надо поменять в базовом классе. Мы меняем базовый класс. И потомки, теперь могут сломаться, придется лезть - чинить.
С другой стороны. Даже если мы не меняем базовый класс. Если мы сильно много кишков базового даем наследникам, они могут как угодно с ними играться, в результате - у тебя почти рандомно может выскочить ошибка в ходе обработки какого-нибудь списка объектов, исключение вылетит в базовом классе, и тебе придется по иерархии наследников пройтись, чтобы найти, кто там в кишках лазил неправильно.
Я с этим вот сталкивался - постоянно. И сколько не пытался придумать А КАК? Так и не смог. Потому - сейчас, я кроме интерфейсов не использую концепцию наследования. Ну, иногда еще когда типа "красиво сделать" - делаю базовый класс абстакнтым, а нужные мне имплементации - приватными вложенными, и через статический метод - создаю.
Можете показать примеры, когда наследование - хорошо и правильно работает. И где почитать о том, как его готовить? А то я почему-то смотрю чужой код и в большинстве вижу, что такие же как я челы, по сути отказываются от наследования, и предпочитают интерфейсы.
>Мы меняем базовый класс. И потомки, теперь могут сломаться, придется лезть - чинить.
Ну так это и есть основная проблема наследования.
>Потому - сейчас, я кроме интерфейсов не использую концепцию наследования. Ну, иногда еще когда типа "красиво сделать" - делаю базовый класс абстакнтым, а нужные мне имплементации - приватными вложенными, и через статический метод - создаю.
Ну так правильно все делаешь. Не совсем понятно, что ты имеешь в виду под "приватными вложенными" и каким именно образом ты статику используешь. Но направление мысли верное - чем меньше бесконтрольного наследования - тем лучше.
Это хорошо еще, что в шарпе множественного наследования нет. Представь сколько хуйни было бы с ним.
Что за котофей? Сорян, не там затестил, у меня в /b бан
> Не совсем понятно, что ты имеешь в виду под "приватными вложенными"
Я имею ввиду что-то типа прикриплейд.
Типа. Ну, типа, когда я не хочу наружу всю вот эту иерархию вытаскивать. Другие примеры: какие-нибудь валидаторы, типа я хочу сделать абстактный валидатор, а внутри прячу типа StringLengthValidator, StringPatternValidator и прочее, наруже будет просто Validator. Но опять, эту фигню я подсмотрел когда лазил в Functional Extensions for C#, и с тех пор иногда применяю.
На любое гуи посмотри.
Там стоэтажное наследование, но иначе будет жесть
Предпочитать делеширование != всегда лучше делегировать
Потому что есть спеки
Понимание таких вещей приходит с опытом. Пиши как умеешь и не парься, со временем научишься. Или уйдешь в менеджеры, весь епам так делает.
В том и дело, что я смотрел на гуи. И там наследование часто используется ВЕСЬМА СПЕЦИФИЧНО. Т.е. те элементы, которые вроде как казалось бы должны быть в одной иерархии - не в одной, а те что как-бы должны отличатся - в одной. В результате - приходится всячески извращаться, чтобы от поведения родителя избавиться, либо добавить нужное поведение которое уже реализовано в параллельной иерархии.
И на фоне этого есть ЖСовские фреймворки, где композитный подход многие используют, в котором нужное поведение своему компоненту ты делаешь как-то так:
<validator v-model="valid">
<presenter :data-source="page.data">
<template #top>
<my-top-bar :actions="page.actions"/>
</template>
<template #bottom>
<paginator v-model="page.meta"/>
</template>
</presenter>
</validator>
Ты занимаешься какой-то хуйней ради хуйни. Просто пиши код, который решает задачу.
не путай разметку (то есть читай описание структуры в текстовом виде, которую можно транслировать во что угодно) со своим вопросом по ООП
это вещи вообще из разных миров.
Та можно было бы и без разметки.
const validator = useValidator();
const paginator = usePaginator();
const topBar = useTopBar();
...
Суть в том, что я поведение компонента могу очень просто под задачу подстроить без наследования.
Я это все пишу на фоне опыта того как, допустим, я делал TreeList для Xamarin, которого нет из коробки. Это была сущая боль. Это были страдания. Литры пролитых слез и бессоных ночей.
А потом - такой же TreeList на Vue - за полчасика хуяк-хуяк и закрыл таску.
А потом ты бы пописал на jetpack compose и вообще ссал бы кипятком от возможности создания франкенштейнов без разметки вообще.
и что с того
мы подходы к гуи обсуждаем или вопрос был по ооп? ты как то определись.
я тебе говорю про конкретные вещи
возьми контролы КНОПКА, КОМБОБОКС, КАРТИНКА и так далее
хоть в своем любимом браузере блин. Они не элементы хмл, они контролы в объектной модели
А потом ты понимаешь что у них есть размер - и вот у тебя рождается базовый класс. А потом ты понимаешь что некторые скроллируемые и вот у тебя еще класс и уже 3 уровня
и так продолжаешь и продолжаешь, плодишь контролы, выделяешь общности и вот у тебя уже нихрена себе развестистая структура наследования.
Пробуешь с делегированием, а получается крайне неудобно
Конечно жс в общем то не имеет наследования (там прототипная шняга), но мы же про стандартный ООП говорим.
Вообще делегирующий подход есть - jetpack compose использует как раз делегирование, а не наследование. Но шарп на это не способен. И вообще это не делегирование ради делегирования, а DSL
вернее не то чтобы не способен.
в шарпе тоже можно сделать как в том же swift combine
и даже сделали же что то ( я видел видосы) в мауи
правда где оно в итоге вместо хамла - я хз.
Но это не то делегирование что "замена наследованию"
это через ектеншены, что немного не то
хотя семантически можно сказать что делегирование.
Шарпаны, дайте совет по ASP.NET core. Мне нужно, чтобы после UseEndpoints выполнился другой MiddleWare, который обрабатывает 404 и при этом возвращает тип IApplicationBuilder. Как такое сделать?
Спасибо за наводку, анонче!
Ну и норм. Я тоже когда-то писал код для себя. Потом в какой-то момент подумал, а какого фига, я это делаю просто так, если за это можно еще и деньги получать.
Их уже даже в 1с нет. Вкат полностью умер.
Только по приколу для пет проекта
но возник вопрос. Препод в видосе создает консольное приложение (.NET Framework) на платформе .net 4.7.2 и на основе его учит, когда есть уже net 8. Стоит ли повторять 1 в 1 или создать на net 8?
Зачекай букву l из солида
Предпочитай композицию
Наследование реализуй в каких нибудь банальных ситуациях типа налседования от класса Person и когда тебе реально нужны реализации в базовом классе.
Также с помощью наследования можно ебонуть мощную поддержку дженериков, переопределяя по сути одним дженериком метод базового класса и при этом сохраняя инвариант.
Также мощь наследования можно понять с помощью гоф паттернов, там какие то поведенческие паттерны выдают приколы через наследования. К примеру с помощью visitor можно ахуенно избавиться от ветвлений для однородных объектов и абстрагировать логику
в итоге олды уйдут на покой, а джунов не будет
и твое место займет бомж из соседней мусорки, что книжку по шарпу бородатых годов нашел и прочитал.
кто тебя покусал и внушил тебе такую чушь?
Почему?
Как я и сказал это один из способов избавиться от ветвлений и абстрагировать логику
Если бы об этом знали разрабы киберпанка то их бы не поливали гавной
А еще это классическое решение проблемы двойной диспетчеризации
ну да, вместо решения этой проблемы можно пойти...на завод грузчиком
Ты о чём? Счастливые те времена потому что можно свои проекты пердолить и переписывать десятки раз.
Когда прогаешь на дядю всё же энтузиазма на свои проекты порой не хватает
Когда ты используешь визитор и медиатор, твой код оказывается разорван на мелкие кусочки. Особенно медиатор в обработчиках ивентов на микросервисах, это полный ебаный пиздец. Потом тебе надо обойти все 100500 мест кода и сложить этот пазл обратно чтобы понять, как эта хуйня вообще работает.
Логику не надо никуда абстрагировать. Такой хуйней занимались во времена GOF, когда пердолили абстрактные фабрики абстрактных фабрик, чтобы посчитать сумму в массиве. В 2024 пишут простой и понятный код.
а ну покажи решение двойной диспетчеризации не через визитор и без хрени типа dynamic и рантаймовых исключений
а мы посмотрим
тебе нигде. ты же калькуляторы пишешь - и те с помощью chatgpt
тут вот чел выше граф редактор делает - вот ему вполне можно применить визитор если он не хочет в рантайме исключения типов ловить.
Каждый школьник-вкатунец пишет то свой редактор, то свою субд. Судя по багажу знаний, ты пишешь целую операционку с нескучными обоями.
ну пишет и пишет. имеет право
ты спросил куда применить - я тебе показал реальный пример
а то что ты там сидишь в своем формшлепском мирке - твои проблемы
жаль тебя....ну или нет.
удивительно что нужно пояснять очевидные вещи
>Препод
Препод из Ромки, как из говна пуля.
>Стоит ли повторять 1 в 1 или создать на net 8?
Если ты хочешь учить шарп конкретно для Юнити, то стоит. Потому, что там под капотом mono по факту, а он по сути и есть попенсорсный .NetFramework
Если ты хотел юзать в геймдеве фишечки из современного шарпа - забудь. И вообще привыкай писать все просто и прямо как топор. За использование того же linq тебе к примеру сразу огурец в жопу вставят.
А ты возьми и забенчмаркай и сравни хотя бы обычный foreach против .foreach() или поиск в обычном цикле или .Where() (ессно не на последнем .Net-е, а на том самом который к юнити прикручен)
Если ты хочешь, чтобы твоя игра была не дергающимся говном, а выдавала стабильные, хотя бы 60FPS, то все современные "бестпрактис" по написанию понятного и поддерживаемого кода идут строго нахрен. В геймдеве в почете скорость.
По смыслу он прав.
Никогда не спрашивай и не слушай на двочах
Тут модер жаба-даун, перебанил половину комьюнити /pr, от чего сидит срёт сам и шизиков развлекает.
Просто открой официальные доки, пришлось потратить 3 секунды гугла, какое нахрен моно и фремйворк 4.
https://docs.unity3d.com/2023.3/Documentation/Manual/CSharpCompiler.html
Я как-то смотрел видосик, там чел сравнивал производительность в задаче посчитать сумму массива. Петушиный linq выдал 40 единиц (миллисекунд, кажется, я точно не помню), а simd - 0.6 единиц, лол. Я вообще не понимаю, нахуй кому в 2024 нужен тот linq. Его в свое время сделали, чтобы впарить мартышкам новую версию вижуал студии, а для разработки это говно без задач.
Что блять?
Ты сравнил ассемблерную векторную команду с LINQ на полном серьёзе?
Ты совсем поехал?
Ну то есть ты сейчас жалуешься, что микроскопом гвозди плохо забиваются.
Поридж, если ты собираешься делать игры, тебе придется думать о таких вещах. Вплоть до того, где какие байты лежат и сколько раз проц ходит в память. Если ты напердолишь абстрактных фабрик и прочих бест практик из книжек, твоя поделка выдаст 5 фпс и обмякнет. Добро пожаловать в программирование.
Как там в 2015, дурачок? На последнем дотнете линк считающий сумму массива точно так же развернется в векторизованный код.
Только кто юзает линк в хай перформанс местах? Ты?
>Поридж, если ты собираешься делать игры, тебе придется думать о таких вещах. Вплоть до того, где какие байты лежат и сколько раз проц ходит в память. Если ты напердолишь абстрактных фабрик и прочих бест практик из книжек, твоя поделка выдаст 5 фпс и обмякнет. Добро пожаловать в программирование.
>Просто открой официальные доки, пришлось потратить 3 секунды гугла, какое нахрен моно и фремйворк 4
Угу. У джавы вон тоже вроде как 21-я версия последняя, а сидят все на 8-й (утрирую конечно) Вот и в юнити так же. Вроде как можно и новое, но по факту, чтобы твоё игроподелие нормально работало везде - хер ты из пределов .Net standarta и frameworkа вылезешь.
Не развернется
> делать игры
> на языке с гарбедж коллектором
Ты там ебобо? Мож РТОС на шарпе еще хочешь?
Давай теперь ты покажешь мне как ты на ассемблере напишешь что-то в духе:
users.Where(x=>x.Role == Roles.Admin)
.Join(posts, x=>x.AuthorId, y=>y.Id, (z, z1) => new {z.Namy, z.Email, z.BirthDate, z1.PostText, PostDate = z1.Date})
.GroupBy(x=> x.BirthDate.Year)
.OrderBy(x=>x.Key)
И потом вернись сюда и сравни количество кода и простоту внесения изменений.
>Поридж, если ты собираешься делать игры, тебе придется думать о таких вещах. Вплоть до того, где какие байты лежат и сколько раз проц ходит в память. Если ты напердолишь абстрактных фабрик и прочих бест практик из книжек, твоя поделка выдаст 5 фпс и обмякнет. Добро пожаловать в программирование.
Я не собираюсь игры писать, я пишу b2b ентерпрайз приложения. В моей сфере фичи гораздо важнее, чем байтоебля, у нас нет времени тратить годы на написание быстрого, но неподдерживаемого кода.
Мне тогда непонятно, на кой хер юнити нужен сишарп, если там из сишарпа ничего не используется?
> если там из сишарпа ничего не используется?
Как и в анриле - просто язык, а не платформа. В юнити и реализация тасок своя на базе корутин.
Жс тоже порой как ембеддед яп юзается и там тоже нет никаких привычных стандартных объектов, повезёт если реализация стандарта полная
Какое место на рынке мобильной разработки занимает шарп?
Почему какой-либо организации может прийти в голову делать приложение на Xamarin, а не на каком-нибудь Flutter?
В чём могут быть преимущества такого выбора?
>Господа шарписты, а расскажите, пожалуйста о мобильной разработке на C#.
Есть мнение, что Xamarin сам не компилит, а транслирует код в Java. Но это неточно.
>Какое место на рынке мобильной разработки занимает шарп?
На уровне статпогрешности.
>Почему какой-либо организации может прийти в голову делать приложение на Xamarin, а не на каком-нибудь Flutter?
>В чём могут быть преимущества такого выбора?
При переносе десктопного продукта (а скорее только лишь какого-то компонента этого продукта) на мобильную платформу.
Если бизнес-логика сложная, то есть ситуации когда проще и дешевле портануть продукт на Андроид C# код, чем переписывать его на другом языке. Это когда надо быстро, это когда надо это сделать "ещё вчера".
>Какое место на рынке мобильной разработки занимает шарп?
Если не учитывать геймдев со всякими юнити, годотом и т.д., то практически никакое.
Я хачю стать начальникам праграмистав им ни нада знать язык дастатачна бить плёткой
> Какое место на рынке мобильной разработки занимает шарп?
На самом деле не так мало. Сильно меньше чем другие, но немало.
> Почему какой-либо организации может прийти в голову делать приложение на Xamarin, а не на каком-нибудь Flutter?
Потому что штат шарпистов, и искать еще кого-то в хуй не уперлось.
> В чём могут быть преимущества такого выбора?
У тебя дохуя уже всего может быть написано на шарпе. Те же всякие хуйни для рассчетов, анализов и прочего, которые по тем или иным причинам должны выполняться на клиентской машине. Лезть, искать документацию (которой никогда нет), искать людей которые знают как проводить эти расчеты(которые уволились 10 лет назад), залазить в исходники неродного языка, это долго дорого и тяжко.
Плюс - экосистема майков. Она буквально лучшее что есть в мире программирования.
Плюс - до недавних времен - поддержка от майков, которая тебе возьмет, какие-то там штуки подкрутит - и у тебя летает приложение, что пиздец.
Плюс, иногда требуется как раз не чтобы нативно выглядело, а наоборот, чтобы на всех платформах одинаково+-. Особенно часто эта хуйня начинается, когда у компании торкает за корпаративный стиль, чтобы все продукты в одной стилистике, с одним набором иконок и прочего говна.
Короче, причин может быть много.
аххахаха
>Есть мнение, что Xamarin сам не компилит, а транслирует код в Java. Но это неточно
абсолютно неправильное мнение. все исполняется на clr рантайме, поэтому пустое приложение и весит так много
и стартует так долго
потому лучше выучить котлин
ну это если не нужно кроссплатформа
но срать на яблочников. они это любят.
С другой - плагины с хотрелодом?
Типа делать какую-то общую сборку Core с интерфейсами и заставлять плагины их использовать?
Вообще, где почитать про реальные примеры с плагинной архитектурой, не на детских примеров, а допустим - какой-то плеер или там игрулька, в которой я хочу иметь возможность подкрутить что-то в dll и не пересобирать все полностью, а чтобы НА ЛЕТУ прилетели изменения.
AssemblyLoadContext?
>абсолютно неправильное мнение. все исполняется на clr рантайме, поэтому пустое приложение и весит так много
>и стартует так долго
>
Не, мнение не из за скорости. Я имею в виду что есть мнение, что C# на этапе компиляции транслируется в Java на уровне исходного, а дальше всё как обычно.
Откуда такое мнение? Есть две причины.
1. Написать компилятор уровня C# не по силам "стартапам" уровня Xamarin. Какой бы Мигель не был гений, но это пиздецовски сложная задача.
2. Если распаковать APK и заглянуть внутрь...
> Есть мнение
Такое ощущение, будто внутри Xamarin происходит какая-то магия, и никто точно не знает, как он работает.
>но это пиздецовски сложная задача.
Что там Котлин? Обозвали препроцессор языком и довольные.
А как щёки надували - "мы компилятор напишем". Написали? Сдулись.
>Я имею в виду что есть мнение, что C# на этапе компиляции транслируется в Java на уровне исходного
что значит есть мнение? тебе говорят как оно устроено, а ты есть мнение
так то есть мнение что земля плоская, но какой смысл об этом упоминать в среде астрономов
>Какой бы Мигель не был гений, но это пиздецовски сложная задача.
есть моно рантайм. почему то его достаточно для написания игр, а тут не по силам
про блазор вообще вспоминать не буду - еще скажи что он в жс транслирует.
>>38394
котлин няшный вышел. но он не транслирует себя в жаву
как и на рантайме дотнета тоже не один язык - но все они транслируют в IL
https://metanit.com/sharp/tutorial/14.3.php
https://metanit.com/sharp/tutorial/18.3.php
Это если вкратце, а за более подробным на МСДН
Там по моему для ячейки можно достать атрибут, который укажет какой excel-тип данных у неё. Тебе надо написать свой резолвер который будет преобразовывать значение в зависимости от него. Простым кастом тут не получится.
Зависит от контейнера в котором находится изображение. Некоторые обрезают по габаритам, а некоторые нет.
Какие контролы не обрезают: Canvas. Но у него есть существенный минус — его локальное пространство бесконечно. Контент не видит границ родителя, как у Grid к примеру. Ты можешь сколько угодно менять размер Canvas, но содержимое под эти размеры никак не сможет адаптироваться, если ты этому контенту сам не передашь информацию.
Все остальные контролы обрезают. Причем может сложиться ощущение, что Border или Grid не обрезают, если размер контента не больше габаритов родителя. К примеру Grid имеет габариты 100х100, а изображение внутри 30х30. Так вот если ты при помощи RenderTransform сместишь изображение за пределы грида, то изображение не обрежется. Но если ты поставишь размер изображения 300х300, то оно обрежется оставив до габаритов родителя т.е. 100х100. При этом изображение все так же может выходить за пределы грида, только вот в уже обрезанном состоянии. А все потому, что RenderTransform в отличии от LayoutTransform пересчитывается постфактум на этапе рендера, когда грид УЖЕ обрезал твое изображение.
Какие уловки можно в этом случае провернуть? Самый тупой это картинке установить Margin в минус. Чем меньше значение (относительно нуля), тем больше ход твоего изображения. Но это ебень, лучше использовать канвас. В твоем случае уж точно.
Можно попробовать тыкнуть палкой LayoutTransform, но я тебе ничего не смогу сказать по этому поводу.
Еще я заметил, что может обрезаться если один контейнер положить в другой. Обычно такое замечаю в сложных вложениях, когда какие нибудь десять гридов упакованы в юзер контрол, который упакован еще в десять гридов. Ты можешь сделать работающий контрол, но потом вложить его куда нибудь и все пойдет по пизде. Этот факт надо учитывать.
Еще информация для справки. Если ты собираешься что-то тягать, то конечно же ты можешь использовать любой контрол и даже заставить двигаться Image. Уж не знаю какой ты способ выбрал: то ли отслеживать MouseMove рамки, то ли картинки, но есть еще один вариант. Если ты в качестве перетягиваемого элемента будешь использовать Thumb, то у него в событиях есть лютая годнота в виде DragDelta — это относительное смешение мыши при перетягивании. Все что остается, это данное значение запихнуть в Matrix.Move, который тоже смещает на относительную величину.
Но есть нюанс. Нюанс с вращением. Если Thumb повернут трансформациями, то дельта будет рассчитываться относительно повернутого объекта. Это может быть как гемором так и фичей. Например, если ты делаешь какой нибудь слайдер, то ты можешь сделать логику для перемещения Thumb по оси X, а если тебе нужен вертикальный вариант слайдера, то ты просто устанавливаешь контролу трансформацию с поворотом на 90 градусов, при этом визуально ползунок будет двигаться по оси Y, но внутри он все так же работает по оси X. Очень удобно.
В этот Thumb ты помещаешь ImageBrush, в котором и будет находиться твое изображение. Причем возможности ImageBrush гораздо шире того же Image. Там можно контролировать масштаб, положение и тайлинг изображения. В свойствах есть же есть так называемый ViewBox, это виртуальная область визуализации и все что выходит за его пределы — обрезается. Такой ViewBox много где используется, например в SVG.
Не знаю, нужно тебе или нет, просто информирую.
А еще погугли что такое Adorner. Возможно рамка, которая показывает область обрезки изображения (как и сами манипуляторы масштабирования/премещения) лучше делать через адорнер-слой.
Зависит от контейнера в котором находится изображение. Некоторые обрезают по габаритам, а некоторые нет.
Какие контролы не обрезают: Canvas. Но у него есть существенный минус — его локальное пространство бесконечно. Контент не видит границ родителя, как у Grid к примеру. Ты можешь сколько угодно менять размер Canvas, но содержимое под эти размеры никак не сможет адаптироваться, если ты этому контенту сам не передашь информацию.
Все остальные контролы обрезают. Причем может сложиться ощущение, что Border или Grid не обрезают, если размер контента не больше габаритов родителя. К примеру Grid имеет габариты 100х100, а изображение внутри 30х30. Так вот если ты при помощи RenderTransform сместишь изображение за пределы грида, то изображение не обрежется. Но если ты поставишь размер изображения 300х300, то оно обрежется оставив до габаритов родителя т.е. 100х100. При этом изображение все так же может выходить за пределы грида, только вот в уже обрезанном состоянии. А все потому, что RenderTransform в отличии от LayoutTransform пересчитывается постфактум на этапе рендера, когда грид УЖЕ обрезал твое изображение.
Какие уловки можно в этом случае провернуть? Самый тупой это картинке установить Margin в минус. Чем меньше значение (относительно нуля), тем больше ход твоего изображения. Но это ебень, лучше использовать канвас. В твоем случае уж точно.
Можно попробовать тыкнуть палкой LayoutTransform, но я тебе ничего не смогу сказать по этому поводу.
Еще я заметил, что может обрезаться если один контейнер положить в другой. Обычно такое замечаю в сложных вложениях, когда какие нибудь десять гридов упакованы в юзер контрол, который упакован еще в десять гридов. Ты можешь сделать работающий контрол, но потом вложить его куда нибудь и все пойдет по пизде. Этот факт надо учитывать.
Еще информация для справки. Если ты собираешься что-то тягать, то конечно же ты можешь использовать любой контрол и даже заставить двигаться Image. Уж не знаю какой ты способ выбрал: то ли отслеживать MouseMove рамки, то ли картинки, но есть еще один вариант. Если ты в качестве перетягиваемого элемента будешь использовать Thumb, то у него в событиях есть лютая годнота в виде DragDelta — это относительное смешение мыши при перетягивании. Все что остается, это данное значение запихнуть в Matrix.Move, который тоже смещает на относительную величину.
Но есть нюанс. Нюанс с вращением. Если Thumb повернут трансформациями, то дельта будет рассчитываться относительно повернутого объекта. Это может быть как гемором так и фичей. Например, если ты делаешь какой нибудь слайдер, то ты можешь сделать логику для перемещения Thumb по оси X, а если тебе нужен вертикальный вариант слайдера, то ты просто устанавливаешь контролу трансформацию с поворотом на 90 градусов, при этом визуально ползунок будет двигаться по оси Y, но внутри он все так же работает по оси X. Очень удобно.
В этот Thumb ты помещаешь ImageBrush, в котором и будет находиться твое изображение. Причем возможности ImageBrush гораздо шире того же Image. Там можно контролировать масштаб, положение и тайлинг изображения. В свойствах есть же есть так называемый ViewBox, это виртуальная область визуализации и все что выходит за его пределы — обрезается. Такой ViewBox много где используется, например в SVG.
Не знаю, нужно тебе или нет, просто информирую.
А еще погугли что такое Adorner. Возможно рамка, которая показывает область обрезки изображения (как и сами манипуляторы масштабирования/премещения) лучше делать через адорнер-слой.
Ах да, я прикрепил картинку, а текст удалил.
На пикрилейтед рамка со скругленными углами обрезает по контуру прямоугольник внутри. Именно что обрезает. Делается это с включенной опцией ClipToBounds.
> Но есть нюанс. Нюанс с вращением. Если Thumb повернут трансформациями, то дельта будет рассчитываться относительно повернутого объекта.
MouseMove также будет относительно рассчитываться
Спасибо за такой подробный ответ, много нового для себя открыл. Про thumb впервые услышал, а ведь куча костылей была мной написана. Удивительное дело конечно, столько пользоваться технологией и все равно натыкаться на вроде бы базовые вещи, которые тем не менее ты не знал.
Вообще, решение я в итоге нашел, костыльное до жути, но тем не менее - засунул картинку в scrollviewer и прокрутил на середину.
>MouseMove также будет относительно рассчитываться
Ты имеешь ввиду метод GetPosition()? Но он рассчитывается относительно указанного контрола.
Смотри пикрил. Левый вариант — это GetPosition(). Когда ты перетягиваешь курсор из точки А в точку B. Ты получаешь смещение относительно нуля габаритов рамки. Тебе нужно произвести дополнительные вычисления, чтобы определить путь A-B. Я уже молчу про то, что MouseMove работает всегда, и тебе надо как-то детектить не просто перемещение мыши, а именно что перетягивание. Тебе придется добавлять собите MouseClick, добавлять переменную последней позиции мыши и кучу всего.
Правый вариант — это как работает DragDelta. В аргументах события тебе УЖЕ передаются координаты смещения относительно точки A.
Кроме того, там есть события DragStarted и DragCompleted для детектинга начала и конца перетаскивания. Есть DragEnter это когда откуда-то еще в твой контрол что-то перетягивают. Так реализуют функционал Dtag n Drop.
Это код из видео просто
И прикриплейд смущает. После остановки клиентов - висит в оперативке вот это вот.
НО. После того как ради прикола запустил еще раз клиенты, но с 10 клиентами - память начала уменьшаться. Полчаса до этого - диспечер задач показывал, такое потребление.
Почему так? Почему оно не освобождается сразу? Если в студии запускать с инструментами дебага - там сразу график вниз падает.
Еще смущает вот что. 14 гигов. Типа на этом сервере гоняю XMLки. До этого гонял бинарный протокол типа модбаса, но проще, 10к меньше 2 гигов потребляли.
Это все из-за XML'ок и сериализаторов? Чи как? Чи шо?
Я не понимаю, куда смотреть
Ну. Типа. Я просто взял NetworkStream и скормил его XmlSerializer.
С модбас-подобным правда я использовал MemoryPool и обычные сокеты, без этого самого NetworkStream
Ну. Если клацнуть на эту строчку - сокеты больше всего.
Больше не скажу, потому что упала студия.
Потому и не смотрю этот профилировщик. На работе есть dotTrace, там хоть не падает от каждого чиха. А вот в студии - сколько не пробовал - каждые второй сеанс - все пиздец, и падает студия(
ты так говоришь будто я тебя заставлял смотреть именно в ЭТОТ профайлер )
я заставлял лишь голову повязать чтобы она не лопнула от ума когда статью на хабре прочтешь.
Я уже прочитал. Меня все же смущает разница между другим сервером который без стрима и с бинарным протоколом. Разница в разы по потреблению.
Интересное чтиво, оптимизация которая тупо затрудняет мониторинг памяти. Вроде в го или жабе с таким же боролись и добились освобождению сразу, жалко в статье не раскрыта идея как победить "это" в шарпах.
AppDomain вроде как освобождает всю память.
Какие подводные?
Какие альтернативы, если клиент не хочет докера, но при этом - хочет чтобы ОДНОЙ КНОПКОЙ, КАК ДЕСКТОП...
Это как? Типа нескольких сборок, которые загружаются одним общим экзешником, но взаимодействуют не через вызов методов, а через сокеты?
В ближайшем приближении - ды.
Понимаю, что в общем целом - такое себе решение. Но если уже есть пачка микросервисов, и никто не думал о том что должны будут частью монолита - это видится самым простым решением, если времени не так много на спринт.
Вы там совсем ебанулись.
Не выебывайтесь и если так приперло напишите мастер процесс который будет запускать/обновлять/гасить весь зоопарк
Батник напиши, который их запускать будет
Долго и много учил C#. Хорошо знаю основу языка, умею работать с базами данных (реляционными и нереляционными), разбираюсь в WPF, а также ASP.NET Core (а еще разбираюсь в разных подходах вроде MVVM, MVC, MVP). Могу как в CodeFirst так и в DBFirst. Знаю как завернуть приложение в контейнер с помощью Docker'а и запустить на каком-нибудь облаке. На Indeed видел вакансию - Angular, .NET, подумал, но пока JS не учил, пользовался только готовыми вещами с bootstrap для своих мелких демопроектов. Еще в дизайне я говно.
Так вот первый вопрос, с текущим набором навыков можно ли начать фрилансить? Если нет, то что нужно доучить?
Если вы пользуетесь зарубежными фриланс биржами или другими сервисами по поиску удаленной работы, то какими? Как вы выводите доход со счета сервиса на российскую карту?
Спасибо что дочитали до конца. Заранее спасибо за ответы.
С такими навыками - иди джуном, попробуй как-то год продержаться. Потом пытайся перепрыгнуть на мидла, и ищи удаленку.
>Какие альтернативы
Искать новую работу и постараться в следующий раз не вляпаться в такое дерьмо, где просят переделать всю архитектуру в последний момент потому, то "клиент не хочет...". Такие вещи как бы перед началом работ, а не после согласовываются.
У нас гибкая разработка, вы нам не подходите.
Смотри, няша.
Вот ты продуктовая компания. Вы собрали с разных бизнесов хотелки, продумали архитектуру. Все отлично. Разрабатываете.
Вот вы выпустили первую версию. Вторую версию. Третью версию... Большинству клиентов нравится то что есть. Вы развернулись в облаке каком-то, они подрубаются и пользуются. Отлично все.
Тут приходит кто-то из маркетинга, говорит: "Там короче клиент, хочет наш продукт, НО У НЕГО ТРЕБОВАНИЕ, чтобы запускалось без докеров и одной кнопкой, КАК ДЕСКТОПНОЕ. На его мощностях. Оч важный клиент. Оч много денег платит. В общем, я ему уже пообещал, что мы через 2 недели покажем ему на его мощностях развернем, сделайте че-нибудь быстрое"
Твои действия?
>ты продуктовая компания
>У НЕГО ТРЕБОВАНИЕ, чтобы запускалось без докеров и одной кнопкой, КАК ДЕСКТОПНОЕ. На его мощностях.
Сказочная ситуация. Кабан бы послал нахуй менеджера с одним таким клиентом. Не по техническим требованиям, а по тому что к хуям ломаяется схема получения денег с клиента за услугу. Можно вообразить такую ситуацию в мелкой компании вообще без клиентов.
Если клиент крупный, и при этом - старый и лояльный, никуда кабан его не пошлет. Проще попросить поднажать, придумать решение, и вообще.
Как-бы бизнес это еще и про отношения. Особенно всякий B2B.
Если клиент крупный, то проще клонировать ему всю инфраструктуру, чем преписывать непонятно на что.
В таких местах где продакт и тимлид такое пропускают в бэклог с дедлайном вчера либо должны платить сильно выше рынка, либо нахуй там работать
>Вот ты продуктовая компания.
Спасибо нахуй. Наелся подобного.
>>43013
>Оч много денег платит. В общем, я ему уже пообещал, что мы через 2 недели покажем ему на его мощностях развернем, сделайте че-нибудь быстрое"
>>43056
>Если клиент крупный, и при этом - старый и лояльный, никуда кабан его не пошлет. Проще попросить поднажать, придумать решение, и вообще.
Когда бизнес позволяет своим продажникам принимать такие охуительные решения (без согласования с разработкой) или еще хуже владелец сам принимает такие решения, то можно с большой уверенностью сказать, что конторе пиздец. По крайней мере в её обычном виде. Это просто сигнализирует о том, что кабан потерял берега и вместо спокойного и методичного зарабатывания бабла и продвижения на рынке, решил погнаться за длинным рублем и катит свой же бизнес в яму.
> НО У НЕГО ТРЕБОВАНИЕ, чтобы запускалось без докеров и одной кнопкой, КАК ДЕСКТОПНОЕ
А такое и правда бывает? Я с таким встречался только на первой работе. Как раз было десктопное приложение, которое должно было быть БЕЗ БД И БЕЗ ИНСТАЛЛЯТОРОВ, УСТАНОВКА ПРОСТЫМ КОПИРОВАНИЕМ. С тех пор за 20 с лишним лет больше такого не видел.
Ну. Вот недавно прилетело как раз. Типа, ну хочет клиент, чтобы можно было просто далее-далее-далее, появился ярлычок на рабочем столе, клацнул, запустил. Надо придумать, как сделать. Я думал-думал, и учитывая, что на все про все - две недели разработки - ниче лучше, кроме как слинковать все это в один проект я пока не придумал.
Написать заявление и уйти на больничный?
>Типа, ну хочет клиент, чтобы можно было просто далее-далее-далее, появился ярлычок на рабочем столе, клацнул, запустил.
Смотри, если ты упорешься и все таки это сделаешь, то крайнем останешься все равно ты. Просто потому, что у клиента все равно будут проблемы и придет он к вам, а их переадресуют тебе и с каждой итерацией ты будешь все больше и больше виноватым. И не тот маркетолог, который пообщещал такие сроки, а именно ты, т.к. взялся за работу и не сделал или сделал плохо. Тебя просто сольют в итоге, как того, кто "завалил проект". Реально сам видел, когда зав.глав.кабана увольнял джуна с такой формулировкой, когда он не смог за пару недель переписать проект с одной библиотеки на другуй (обе которых он до этого не трогал даже.)
А вот если сразу отмазаться от такого задания, ну хуй с ним, побудешь плохим пару дней, зато потом переключаться на другого лоха который взялся и не смог.
Как же ты прав, анон. Сам в такую ситуацию попадал из-за омежности и страха сказать нет. Сейчас понимаю, что лучше сразу пересилить себя, чем потом оправдываться и быть крайним.
сейчас я делаю вот это:
#if DEBUG
int _debugValue = 5;
#endif
препроцессорные куски неистово бесят.
Для какого кейса тебе это нужно?
А вообще моё мнение такое - если нужно активно использовать код, который работает только в Debug сборке, то нужно выделить для него абстракцию (сигнатура метода, интерфейс, абстрактный класс), сделать две реализации этой абстракции (одну денежную, другую релизную), и только в одном месте с помощью директив препроцессора указать, какую из них для какой конфигурации нужно использовать. Так у тебя весь код не будет увешан директивами препроцессора.
Вот к примеру у меня vps ubuntu с 2мя ip, как мне выбрать через какой ип делать запрос?
Погугли хттп протокол. Если коротко то хост передаётся в хедерах после установки коннекта с ипом. Дальше думаю сам раскуришь, один фиг тебе с этими знаниями всю жизнь работать
Добавить SocketsHttpHandler и в нём забиндить сокет к нужному локальному IP.
См. https://stackoverflow.com/questions/65930192/
Просто я вижу, как у меня весь GC засран акшонами. Они появляются, сразу исчезают, их GC пытается вилкой чистить.
Но блин, как же с ними удобно-то.
лямбды что ничего не захватывают - они создаются как методы класса
те что что то захватывают - хз не помню
а вот как раз методы постоянно создают делегаты
У меня примерно такой код на одном участке, который из одной апишки в другую гоняет
И в профилировщике - я вижу примерно картину как на прикриплейд со сборками мусора постоянными.
Если смотреть, то создаются и постоянно исчезают Action. Что странно, ведь моя лямбда должна быть Func<Task>, а ее вообще там не видно.
Перепроверил переписав без лямбд. В общем, дохрена этих Action'ов создает HttpClient. Значит не в моем коде дело. Теперь вопрос - нахуя он это делает и че мне с этим делать? Да, оно чистится, но меня смущает, что постоянно дергается GC.
Или я тупой и вообще не понимаю что происходит и так и надо.
ничего ты с этим не сделаешь. ну в этом и суть рантайма - чистить мусор и не заморачиваться ручным управлением
ну да, мелкие сделали херь с делегатами методов.
- Апи №1; общая либа с модельками запросов и ответов; апи №2, пользующееся апи №1
- Огромная лень писать клиент самому
Попробовал сгенерить клиент через Kiota (github.com/microsoft/kiota), столкнулся с тем, что второе апи пользуется в контроллере моделькой запроса из общей либы, но в сгенеренном клиенте все модели создаются заново с теми же названиями, и получается херня какая-то.
Собственно, вопрос: есть ли генераторы клиентов, которые могут использовать существующие модели или хотя бы наследоваться от них?
>получается херня какая-то.
Не похуй ли? Как раз весь смысл генерации в том, чтобы кнопку нажать и пользоваться.
Если у тебя есть потребность лезть руками в генереный код, то ты очень не прав, прям пиздец как не прав.
>есть ли генераторы клиентов, которые могут использовать существующие модели или хотя бы наследоваться от них?
Даже если и есть, то все равно они накрутят поверх свои обертки и ты не сможешь ими пользоваться.
Нормальный код. Чтобы студия не заебывала про null, напиши перед свичем проверку if null throw ArgumentNullException. Сравнивать лучше через InvarianCultureIgnoreCase. Можно, конечно, заменить на Dictionary, но он занимает место в памяти, так что чисто вкусовщина. Мне больше нравится свитч, так ты сразу видишь все варианты, а со словарем хуй поймешь что там лежит.
Посоветуйте книжек или уроков С# через разработку игорей или для создания чего либо по Информационным Системам
Так то нужно написать программу для диплома по Информационным Системам. Вот и думаю как можно совместить эти направления, ведь у меня времени только год с лишним.
Появилось время и надо заняться, иначе опять пустая РАБота все силы сожрёт и не до уроков и мечты свалить в другой город.
В реальности я бы написал как пик 1, но если хочется выебонов то пик 2
property.GetCustomAttributes(true).Where(a=>a is LocationAttribute).Cast<LocationAttribute>();
Хуя тут. Спасибо. Теперь ещё компактнее код можно сделать.
Ну а что не так, анон? Свитч не позволяет использовать typeof, и за счет решение с ифом менее подвержено ошибкам.
Читаемость, удобство обслуживания, меньше вероятность проебаться, возможность заинкапсулировать какую-то доп. логику в экстеншене для enum.
Это не говоря уже о том, что портянка из if...else..if...else ни одного нормального код ревью не пройдет.
Плюс, при необходимости, все это очень легко преобразовать в что-нибудь вроде Dictionary+Resolver, а содержимое словаря потом вообще в конфиги вынести.
Я бы так сделал, лул.
Хотя не делал бы. Я вообще не понимаю, нахуя это делать. Ну да ладно, раз ты делаешь - значит надо.
Чуть допиленная версия.
>портянка из if...else
Наркоман, ты написал точно такую же портянку из матчей.
>содержимое словаря потом вообще в конфиги вынести
А потом сидишь и два часа пытаешься понять, какого хуя простейший код не работает. Или работает у тебя, а на проде падает, это самая веселуха. С ифами все было просто и понятно, с конфигами джун-долбоеб насрал абстрактными фабриками и хуй проссышь, откуда данные берутся.
Я уже на заводе
Может быть расширение для report написать с осмысленным названием. Типа .report.NextRow...()
А если у меня название метода CreateReportBody, то может так и оставить? Думаю, что будет понятно, что там смещение на сколько-то. Хотя я хуй знает. А что за расширение?
Но за каким-то хреном конструктор у него Internal, в итоге я не могу реализовать этот класс, потому что возникает ошибку:
CS1729 "PathSegment" не содержит конструктор, который принимает аргументы 0.
Это что за извращениие?
Реализуют интерфейсы, а не классы. Классы наследуют.
Потом, написано же в доках:
>Although this class is abstract, it is not publicly extensible.
охуенчик, спасибо
А как вообще бороться с подобным? Я хоту создать свой собственный сегмент.
Никак, код овнер так сказал, значит так надо
Либо через рефлексию, но за такое нужно битой по хребту пиздить
В rider работает hotreload?
Я думаю, там какой-то код есть, который умеет работать только с существующими сегментами, а если ты сделаешь свой, то всё наебнётся.
Это говнокод, конечно, но его везде можно найти.
>>48931
>>49129
Какие же они изверги.
Может сделать свой контейнер, который будут содержать как готовые классы сегментов, так и мои собственные. Только хз как их объединить. Может сделать коллекцию DependencyObject.
И этот контейнер будет посредником, куда пользователь кидает что хочет. Потом контейнер все это дело обрабатывает и конвертирует в новый список существующих сегментов.
Непонятно как это потом обновлять. Одно дело, когда пользователь кидает весь список, а другое дело, когда меняет точку в каком-то сегменте.
> Одно дело, когда пользователь кидает весь список, а другое дело, когда меняет точку в каком-то сегменте.
У меня только вариант - подписываться на изменение коллекции точек моего кастомного сегмента и модифицировать точки связанного элемента.
Да, наверно так и поступлю.
>hotreload
А кто-то им вообще пользуется?
Просто по моему это хуйня почти без задач, годная разве что когда что-нибудь мелко-консольное пишешь. Более-менее объемный сервис хер ты на горячую изменения сможешь применить и быть уверенным, что оно не пойдет по пизде и все равно потребует полного перезапуска.
>>49133
Не, не будет работать. Эти сегменты по любому должны принадлежать только одному родителю. Не считая того, что там целый зоопарк иерархии, типа сегменты должны находиться в PathSegmentCollection, а те в PathFigureCollection, а та в Shape.
Какая же хрень ... как же задрали все эти велосипеды. Хочешь МVVM - сделай свою библиотеку Windows. Хочешь шейпы — сделай свою библиотеку Media. Удобно, пиздец.
я пользуюсь - есть заметная разница один микрочеликовый плагин перезагрузить или все приложение+плагины.
хз что бы без хотрелоада делал, вскрылся бы наверное
Есть задачи, с сильным вложением действий и каждый раз ждать 10 минут чтобы дойти до нужной точки, это вымораживает.
keyset пагинация по факту и предназначена для работы со структурированными данными. Либо упорядочивай по guid-u (при генерации ключей например), либо по другому признаку. Если его нет, то вводи.
Вообще, в принципе, получать неупорядоченные данные из БД такое себе,
Но сразу говорю, что генерировать упорядоченные guid-ы такой себе способ. Спорно и не очень распространено. Просто по тому, что если тебе нужна упорядоченность по ключу, то проще взять какой-нибудь long и быстрее и эффект тот же.
Но упорядочивать по Id тоже плохая идея, он не для этого нужен.
Проще для этого (упорядочивания) временную метку использовать.
Насколько я понял надо добавить какое-то поле long типа и по нему упорядочивать, правильно? Я ещё видел реализацию через DateTime
Это зависит от того, как у тебя данные в БД вставляются. Если строго по одному, то DateTime норм способ. Не надо дополнительный sequence вводить, просто юзаешь DateTime.(Utc)Now при создании записи и все. Если же предполагается вставка пачками, тогда лучше использовать что-то отдельное с последовательностью.
Понятно, спасибо.
Попизди мне про перезагрузку плагинов средствами студийного релоада.
А с в контексте сервисов - там во-первых сразу x2 с какого-то хуя оно берет и разваливается к хуям.
Про юнит и интеграционные тесты я так понимаю тебе не рассказывали...
Ну да. Ведь лучше хуевый хотрелоад, чем за 0,0000000000001 секунды оказаться в нужном месте с помощью тестов.
Берешь, и как нормальный человек добавляешь: Created, который генерируется при вставке, по нему сортируешь, а дальше паггинируешь как хочешь.
Да. Как нормальный человек делаешь:
public abstract class BaseDbEntity {
public Guid Id { get; set; }
public DateTime Created {get; set;}
public DateTime Updated {get; set;}
public DateTime? Deleted {get; set;}
public bool IsDeleted {get;set;}
}
Ой, ребенок, ты даже близко не представляешь что это. Я понимаю, что в рамках круда это не нужно, но просто не умничай, а то веет тупостью.
Как вы ламеры уже достали, про юнит тесты он рассказал, ну просто гений же.
Прочитал, что офсет медленный. Поэтому и пошёл что-то другое искать
Си решетка
Два кобола.
Чем шарп.
Второй метод, не статический, обращается к свойству родительского класса.
В чем их различия с точки зрения аллокаций? Или аллокиции вызывает сам факт использования переменной и разницы нет никакой?
Посмотри в байткод
Казалось бы, недавно ИТТ выяснили, что Freezable классы пукают событием Changed по любому поводу, и биндинги за каким-то хреном на этот Changed подписываются, хотя их никто не просил.
И что бы вы думали? Пытаюсь я, значит, забиндить класс PointCollection к ItemsControl.ItemsSource и хуюшки. Никакой реакции на изменение итемов коллекции. Событие Changed происходит, а обновление биндингов - нет.
Просто ссаный бардак. И вроде бы ты уже разобрался с ситуацией, вроде бы даже смирился с ней, и вот тебе на. Мне кажется, что мысли женщины последовательнее, чем ссаная впф отрыжка майкрософт.
какого изменения ты вообще ждешь?
ItemsSource следит за событиями обсервабле коллекции, а твой PointCollection их не производит не будучи этой самой обсервабле. Зачем тут то биндингу следить за фризабле - никому непостижимо.
это у тубя в голове (твой череп на фото???) чет не то, раз для тебя вообще норма фризабле коллекцию изнутри менять.
>их не производит не будучи этой самой обсервабле
Запускает событие Changed. И биндинг на этот Changed подписывается, это мы уже обсуждали.
>Зачем тут то биндингу следить за фризабле - никому непостижимо.
Вот я тоже самое писал, но тут сидел чел и доказывал обратное.
Заходишь ИТТ и получаешь примерно такой диалог:
— Нахера биндинги подписываются на событие Changed содержимого в свойстве?
— Ну это же фризабле, ты что дурак?
Через неделю:
— Почему биндинги не подписываются на событие Changed?
— А нахера им подписываться, ты что дурак?
>раз для тебя вообще норма фризабле коллекцию изнутри менять.
Мне надо добавить/убрать точки кривой. Как по твоему это еще делается?
Сеттер фризибле свойства разве возможно вызвать? Ну типа чтобы событие сработало, поток должен провалиться внутрь сетера и дернуть делегат. Если этого в происходит, то и хендлеры никто и никогда не вызывает.
Если я правильно понимаю о чем идет речь.
Есть код:
// SomeClass.cs
while(true){
Thread.Sleep(1000);
MyEvent(this, EventArgs.Empty);
}
// SomeOtherClass.cs
for(int i = 0; i < 1000; i++){
new Thread((_) => someClass.MyEvent+= (_, _) => Console.WriteLine(Thread.CurrentThread.Name)).Start();
}
Что будет выведено в консоль?
Ты путаешь Freezable класс с режимом IsFrozen. Если IsFrozen == true, то менять содержимое не сможешь, но если false, то можешь. Первое устанавливается, если ты инициализируешь класс в xaml, к примеру.
>Если этого в происходит, то и хендлеры никто и никогда не вызывает.
Я повторяюсь. Событие Changed происходит.
Раньше, когда я демонстрировал случай с ValueConverters, биндинги реагировали на это событие, вопреки логике т.к. биндингам нет дела до содержимого свойства, их интересует событие PropertyChanged INPC класса, в котором это свойство находится.
Короче происходит какая-то аномальная дичь, объяснение которой у меня нет, а хотелось бы.
биндингам нет дела. а вот контролам есть
1 ты меняешь внутри фризабле что то и получается событие Changed
Опустим глупость подхода менять иммутабельные по семантике коллекции и оставим их психиатрам будущего
2 биндингу плевать на то, что ссылка осталась прежней, он вызывает подписку в контролах "значениетамченжед"
3 itemsControl вызывает мфк view = CollectionViewSource.GetDefaultCollectionView для нового source
Который, как известно, вернет одну и ту же ссылку для одной и той же коллекции
4 и далее делается проверка
if (_collectionView == view)
return;
5 занавес.
Братиш, зачем тебе это знать?
>Опустим глупость подхода менять иммутабельные по семантике коллекции
А как? Как менять цвет кисти, к примеру? Как менять трансформации? Да любой контрол наследует фризабле.
>2 биндингу плевать на то, что ссылка осталась прежней, он вызывает подписку в контролах "значениетамченжед"
И что? Мой пример с биндингом показал, что конвертер срабатывает даже если ссылка на объект не изменилась. Причем это тоже была коллекция, только она называлась GradientStopCollection. Для понимания ситуации, есть свойство:
public GradientStopCollection MyGradientStops
{
. . .get => _gradientStops;
. . .set {
. . . . . . _gradientStops = value;
. . . . . .OnPropertyChanged(nameof(MyGradientStops));
}
}
Я привязываюсь к этому свойству и туда же цепляю ValueConverter.
GradientStopCollection содержит итемы GradientStop, а те имеют свойства Offset и Color.
Так вот, я меняю свойство Offset одного из итемов GradientStopCollection, и срабатывает метод Convert(). Почему? Экземпляр в MyGradientStops не изменился, а значит не было вызвано событие OnPropertyChanged, но конвертер отработал.
Вероятно конвертер или контрол подписались на событие GradientStopCollection.Changed. Зачем-то. Но на PointCollection.Changed подписываться не хотят.
>И что? Мой пример с биндингом показал, что конвертер
Да епрст. Конвертер срабатывает потому что
1 биндинг видит твое Changed и орет об этом
2 значение вычитывается потому что собственно биндинг его и вычитывает чтобы передать в ЗначениеТамЧенжед в контроле
3 контрол видит что ссылка на новое значение равна старой и ничего не делает
2 и поэтому срабатывает конвертер
Ах вот оно че. Понял.
Напиши какой нибудь 3д-рендер с трассировкой лучей, или распарси книгу. В общем любая задача, где есть куча независимых друг от друга данных.
Но ты попрактикуешь и забудешь. Проблема всех студенческих работ в том, что задача выдумывается под решение, а не наоборот. Из-за этого, условия задачи слишком идеальны и далеки от реальности, они избегают острых углов.
Даже туториалы этим страдают — там всегда описывается идеальный случай в вакууме.
Вообще стоит влезать в подробности, если ты знаешь, как работает env и композник?
В доке докера как ни странно. А всё что ты перечислил относится к кэшированию. Если начиная с первого шага контекст и команды совпадают то шаги будут взяты из кэша до первого расхождения. Потому делается всё что бы пакеты и зависимости переиспользовались.
В целом тот докерфайл что у тебя на скрине вроде и работает как должен но очень сомнительный
если да, то где про такое почитать можно?
Ну гуглишь готовые либы на шарпе для гугла и яндекса, если их нет или не нравятся пишешь свои, склеиваешь костылями.
Тупой вопрос уровня "а как какоть"
>как написать веб сервис на C#
>как вызвать веб апи на C#
>ооп С#
>google docs C#
https://www.google.com
Как мне сгенерировать на их основе веб-приложение?
На жаве просто при создании проекта: генерейт веб-сервис фром WSDL
Да, не ради любопытства или чтобы доебаться спрашиваю. Ну, вот клиент предоставил WSDL дохуища, говорит - это апи которое от вас требуется, чтобы интегрироваться. И я начал руками это говно реализовывать, понял что дохлый номер, не предназначена эта говнина чтобы руками это делать.
Но хуйнуть сервис на жаве - наш техлид не позволяет, кричит, что надо все на .NET делать, а то разведем так зоопарк и вообще.
> Почему нельзя сразу же скопировать все файлы в папку?
Можно. Пизды получишь от админов билд-сервера только через пару дней и справку о профнепригодности.
https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs,2975f0aa875d4a32
Но когда я использую класс System.ArgumentOutOfRangeException на практике, то мне выдает очень скромный список доступных методов (пикрил).
Просто таска как повсеместно в аспе
>с какой нибудь долгой операцией
Зависит от того насколько требовательная операция.
Можно запустить асинк метод с токеном отмены. Гугли CancellationToken. Принцип которого в том, что как только метод завершает свою работу, он дергает токен и у тебя вызывается событие, что работа метода завершена.
Еще есть CompletionToken, например для создания диалоговых окон в асинхронном режиме. Метод будет ожидать завершения таска до тех пор, пока в токене не установится соответствующий флаг завершения или отмены.
У меня на нем же ожидается завершение приложения.
Если операции слишком требовательные, чтобы работать вместе с другими, то в этом случае используется Thread.
Не понял, асинк же это про другое, когда нужно линейное выполнение асинхронных операций без блокировки UI нити. Мне же надо что бы крутился постоянный фоновый процесс, грубо говоря сервис.
Таски это абстракция над тредами, да они могут в одном треде исполнятся, но могут и в разных
Если таких операций немного - тред лучшее решение. Особенно, если там никаких доступов к разделяемым ресурсам.
Тред это же совсем каменный век. Обычно рекомендуют Task.Run(... LongrRunTask)
Большую часть времени - все вроде ок работает.
НО. Бывают случаи, когда возросла нагрузка, и написали дохуя всего. Запустилось дохуя этих вот тасок. Тредпул - сразу в небеса. Процессор - тоже охуевате. Там еще эксепшины в части тасок понлетели - и все страшно вообще стало.
Вот как это контролировать? Как сделать так, чтобы это было управляемо и предсказуемо, а не вот такой рандомный бред.
Я вот ради интереса заглянул в DotNetty и там какой-то свой эвент-луп, какой-то свой тред экзекутер. И поведение как раз то что нужно мне. Но там оно так страшно и по жававским канонам написано, что я с трудом понимаю, что там за что отвечает и как оно вообще работает. Может быть где-то есть другие примеры как сделать управляемой обработку каких-то потоковых задач, которые еще и асинхронные, а надо чтобы они все как-бы конкурентно обрабатывались нормально.
>Запустилось дохуя этих вот тасок
ну запустилось и уперлось в тредпул. Ну да для И/О задач там свои настройки
но чем тредпул отличается от своего екзекутора то
свой нужен для других задач когда ты хочешь точно контролить выполнение чего то этакого чего пулу не доверить. Что то долгое или альтернатива контексту синхронизации.
В общем. Надо было срочно сделать хуевину, для дебага и диагностики работы.
И я СДЕЛАЛ СТАТИЧЕСКИЙ КЛАСС, и в нужных мне местах - просто дергаю нужные мне методы, которые наполняют диагностической информацией всю мою хуйню.
Как мне дальше жить с этим?
И чë? Я по дефолту пишу статические классы. Нестатические пишу только тогда, когда без них вообще никак не обойтись.
Статическое классы выглядят всрато только потому, что все себя в этом убедили.
Мне сказали: СРОЧНА, НАДО ДИАГНОСТИКУ.
Если делать синглтон классический - разницы особой не было бы.
А если делать то что на DI я бы все еще прокидывал бы в конструкторы этот самый синглтон, там 5 лет разработки шизом, который все через конструкторы передает.
> Если делать синглтон классический - разницы особой не было бы.
Ну так и сделал бы.
У нас впф апа, так там никаких новомодных di. Только папочка с полутора сотней синглтонов половина дублирует функционал, потому что проще написать с нуля, чем разбираться в уже написанном
>У нас впф апа, так там никаких новомодных di.
и правильно
имею фреймворк с тотальными нарушениями принципов
1 мультиоконность, (в жопу однооконные приложения по типу телеграм - кстати даже они сдались и дали возможность вынести чат в окно ))))
2 при этом диалоговые окна принадлежат к конкретно окну кто родитель, а не блочит все окна
3 DI использую от майков, но использую его на уровне вьюмоделей как сервислокатор (или фабрику)
4 везде лайфтаймы. никаких weak, только !!!СТРОНГ!!!.Вплетено в основу всего. Все, что куда то подписывается, обязано разобраться в каком лайфтаме оно живет.
окна и контролы тоже завязаны на лайфтаймы (хотя WPF в этом отношении брррр со своими "а тут у нас Unloaded не вызывается ха ха")
5 Везде протаскивается Context (как в андроиде) который определяет контекст вьюмодели и потому нет никакой проблемы вызвать диалоговое окно без бубна "а как найти окно родителя". При этом оно конечно не завязано на сборку вьюх ибо MVVM не должна иметь этой зависимости.
и точно такой же фреймворк где я пытался делать по правилам - aggregation root, не использовать di как сервис локатор, вьюмодель живет без контекста
Угадайте какой используется для реальной работы, а какой заброшен нахрен
А потому что пока там в виларибо всякие там чистый код мудрят, в вилабаджо уже на заработанные деньги устроили оргию
Диагностика нужна такая, чтобы ее мог проанализировать не только я или другой программист, а условный Петрович и принял решение.
В духе:
- Петрович, тут пришел плохой пакет, это не сервер сломался, а кто-то бяку шлет.
- Петрович, там у тебя место на диске заканчивается, ты это, сделай чего-нибудь, а то все наебнется
- Петрович, кто-то в БД полез кривыми руками и поломал справочники, запусти-ка восстановление справочников
С решарпером дефолтное поведение
Спасибо.
>Не понял, асинк же это про другое
Знал бы я про что ты ведешь речь, ведь задача не описана.
>без блокировки UI нити
Любой нити, в которой запущен асинхронный метод. Иногда нет смысла создавать отдельный тред, если операция не особо требовательная, просто она имеет множество итераций, ожидание которых и тормозит работу. Ну или операция слишком часто возникает и недолго живет, что создание треда не очень уместно.
Если у тебя сервис, тогда вероятно уместнее использовать треды.
Везде гошка нужна либо быть помидором на шарпах
Я с годом опыта на шарпах смог устроиться в большой банк писать всякий бэкэнд на шарпах на мидлплюсплюс позицию. Правда у меня до этого было лет 10 всякого байтоебства на низкоуровневой дрисне.
С таким бэкграундом ты и на го и на питон смог бы устроиться без проблем имхо
А какой цвет банка если не секрет?
Мда, моя галера только в топ 15
Почему OpenTK такое кривое тормозное говнище?
Какого рода пекарня нужна-то?
Что не презентация майков - у них макбуки позапрошлого поколения.
Попробуй ансейф.
Вот сейчас у меня вот так:
Task<IActionResult> OnSendMessage(Message msg)
{
await _messageHub.Broadcast(HttpContext.User, msg);
await _statistcQueue.Enque(HttpContext.User, msg);
return Ok();
}
И с этим как-бы проблемы.
Во-первых. Даже не смотря на то что статистика сама обрабатывается в фоне - все равно какое-то время надо подождать, пока в очередь можно записать.
Во-вторых. Если много статистики - у меня под капотом - пулл обработчиков начинает раздуваться, и в определенный момент - NpgSql - начинает матом ругаться, что больше нельзя выделить подключения.
В-третьих. Судя по профилированию - 20% всего времени приложения - занимается обработкой этой статистики, и если я симулирую активную хуйню с рассылкой сообщений - видно что тормозит все это дело, и эти 20% были бы не лишними.
Есть кастомный составной контрол и надо получить контрол как параметр при нажатии на него. Такое чувство что фреймворк ппц сырой.
1. зачем рассылка в хаб?
2. запускай заливку статы в бд максимум в 2 потока раз в 30сек или когда будет минимум 1к записей в очереди/баге
3. вставляй батчами по 1-2к записей
Я если чество вообще не представляю как ты статой смог выбрать весь пул коннектов. Для твоей задачи нужно бэкграйнд воркер сделать который будет заниматься разбором очереди
> Я если чество вообще не представляю как ты статой смог выбрать весь пул коннектов
Ну. Смотри.
Вот мой тест:
HttpCleint http = new HttpClient();
var tasks = Enumerable.Range(0, 10000)
.Select(async (x) =>
{
await Login(http, x);
while(true){
await SendMessage(http, x, new Message{ body= $"Hello from {x}"});
}
});
await Task.WhenAll();
Вот код который обрабатывает очередь:
async Task Run(CancellationToken stopToken)
{
while(stopToken.IsCancellationRequired)
{
// ждем пока в очереди что-то появится
var workItem = await _queue.Dequeue();
// берем из пула ворекра (в случае если пул пустой - создаем нового)
var worker = _workerPool.GetWorker();
try
{
// тут будет создан контекст для подключения к pgSql
// выполнена вставка и сохранение
// освобожден контекст
await worker.ProcessWokrItem(workItem);
}
// возвращаем воркера
finaly{ _workerPool.Return(worker)}
}
}
> Я если чество вообще не представляю как ты статой смог выбрать весь пул коннектов
Ну. Смотри.
Вот мой тест:
HttpCleint http = new HttpClient();
var tasks = Enumerable.Range(0, 10000)
.Select(async (x) =>
{
await Login(http, x);
while(true){
await SendMessage(http, x, new Message{ body= $"Hello from {x}"});
}
});
await Task.WhenAll();
Вот код который обрабатывает очередь:
async Task Run(CancellationToken stopToken)
{
while(stopToken.IsCancellationRequired)
{
// ждем пока в очереди что-то появится
var workItem = await _queue.Dequeue();
// берем из пула ворекра (в случае если пул пустой - создаем нового)
var worker = _workerPool.GetWorker();
try
{
// тут будет создан контекст для подключения к pgSql
// выполнена вставка и сохранение
// освобожден контекст
await worker.ProcessWokrItem(workItem);
}
// возвращаем воркера
finaly{ _workerPool.Return(worker)}
}
}
и это неправильный. где await у GetWorker()
Я специально не жду, чтобы очередь не забивалась... Типа при большой нагрузке - там она разбухает и оператива в небо улетает...
Зачем тебе пул воркеров? Тебе одного хватит который будет здоровыми батчами инсертить. Если потом будет переезд на кликхаус то всё к этому и сведётся т.к. кх ненавидит инсерты по 1 записи.
И не захватывай ctx.User полностью, бери из него только то что нужно, что бы гц мог собрать всё а в памяти оставались только записи статы которые можно хоть десятками тысяч хранить в памяти без распухания кучи
Оверинжинеринг.
> Зачем тебе пул воркеров
Чтобы если динамически нагрузка возрастала - больше обработать можно было... И при этом не тратить время на создание нового воркера каждый раз.
Ну. Я пробовал батчить кстати.
И вот с батчами - сложность в том, что непонятно, а какой размер-то должен быть, чтобы мы решили: ПОРА таки в БД это отправлять.
Плюс, а если у нас наоборот - нагрузка медленная - эта статистика не наберется на батч. Делать хитрую логику: ну, если прошло 5 минут с последней вставки - то так и быть - вставляем что есть, а если не прошло, то вставляем при достижении лимита - мне как-то не нравится.
Чел, у тебя буквально один цикл в котором
если с прошлой вставки больше 120сек или в очереди больше 5000к сообщний
то пишем
спим 1 сек
И скажи эта логика сложнее всей той ненадёжной жрущей ебалы которую ты защищаешь?
Я не защищаю же. Я ж потому и спросил, что возникают проблемы если нагрузка дюже большая.
Просто отвечал на вопрос: "Зачем тебе пул воркеров"
Ладно. МБ правда, сделаю вот так вот. И заменю каналы на обычную конкурентную очередь.
Хочу в мышинное обучение. Знаю, что самым распространённым является богомерзкий змей, но есть ещё прекрасный, как я слышал, ML.Net. Т.е. я не хочу уходить из инфраструктуры и синтаксиса дотнета, но понимаю, что для питона много всего, а для МЛ Нет нет нихуя.
Что делать?
В питон идти, расширять кругозор. Моё имхо.
Ну теперь там инфраструктура, конечно. Это с положительной обратной связью система.
К языку претензий нет, просто не хочется с 0 начинать.
Норм, я на неделе пощупал мл.нет без особых знаний по мл. Гайды на мсдн нормальные. Собрал модель мультиклассификатора, обучал на рабочих данных. Показал начальству и объяснил, те кипятком ссали.
Сказали выделять рабочее время и допиливать.
Заебумба.
Проблем - куча.
Вот самый простой пример. Студия не может понять, че же за типы такие. Хотя у меня включен анализ всех проектов в решении.
Перестает работать переход к определению и реализации.
Не дай бог ты решишь переименовать какое-то свойство, все, потом бегай по всему коду и руками переименовывай.
Но да. Надо уточнить, что это вот в таких больших солюшинах. На работе всего 100 проектов в солюшине и пекарня с i5 и 16 гигами вроде пока справляется.
Если ты только вкатываешься, проблемы у тебя не скоро возникнут.
Вообще, по интервью бывших разрабов с гугла - у них там еще хуже, и потому какие-то ебанутые решения придумывают, но чтобы не врать - не буду пытаться вспомнить, че они там напридумывали, чтобы на макбуках-хромбуках с этим работать.
Тебе же дали ответ как майки со своими репами работают что бы разом всё не прогружать
Ну, мне ответ-то дали.
А я уже отвечаю на вопрос - какие собственно проблемы.
Ну и да. Все равно. А как мне, если я не разраб из майков-то понять вообще, че мне надо выгрузить, че мне не надо? Надо не вот эти вот обходные пути придумывать, а какую-то ленивую подгрузку делать. Типа вот я открыл кестрелл, оно видит, что кестрелл - ссылается на вот это. Это подгрузил. Пока я не полез туда - не подгружать остальное. Как полез - подгружать. Было бы намного лучше я думаю. А как это реализовать - пусть разрабы студии придумывают.
Чел, там и так ленивая загрузка есть.
1. В репе везде разложены пресеты что нужно грузить а что не нужно
2. Есть волшебная кнопочка загрузить зависимости проекта
Вот, я даже твой slnf нашел для кестрела. И жмакнул на это "загрузить зависимости проекта"
Не работает.
Че дальше?
Я тут думаю вот над чем.
А как скейлить монолит со стейтфулл протоколом? Не http.
Пока что я вот что придумал только.
Выделить некий Хост. Этот хост - должен быть тем местом, куда подключаются клиенты.
Выделить серверы. Это те кто на самом деле логикой занимаются, обрабатывают этот протокол.
При старте - серверы - говорят хосту: Я существую, вот мой ip-порт, если что, я на связи.
При очередном пакете от клиента, хост проверяет, знает ли он к какому серверу привязан клиент. Если знает - просто передает все что передано - этому серверу, то что придет от сервера - передает обратно. Если не знает - увеличивает значение счетчика, и просит сервер принять, если сервер готов принять новую сессию - привязывает это соединение к этому серверу и начинает передачу.
Если сервер упал - хост должен узнать об этом, и убрать из списка активных хостов упавший. Все соединения, которые были привязаны к этому серверу - закрываются. При попытке восстановить соединение - они будут перенаправлены на новый сервер.
Но я тут вижу проблему. А если хост - упадет? Как его скейлить?
Хуй знает в чём твои проблемы. Просто прошёлся по мдшке с инфой как начать разработку и всё работает (кроме решарпера который увидел фантомные ошибки, но оставим это на его совести)
Ты не представляешь, насколько я согласен с этим.
Но тут чисто организационный момент. Руководство сеет шизу, что надо для каждого репозитория - писать отдельное письмо султану и просить доступы. к конкретному репозиторию, поясняя откуда ты узнал про этот репозиторий, зачем тебе доступ и т.д.. Соответственно, уже разрабы - не хотят в этой хуйне участвовать и начинают делать в духе: "Otdel1Repo" внутри которого все проекты, а в проектах уже суперсолюшины.
>Руководство
Согласен - шиза (вангую, что какая-то продуктовая контора, где владелец считает свой продукт самым-самым и трясется, что конкуренты украдут его "уникальные" разработки). Но разрабы тоже лопухи, что повелись и решили это таким способом. Можно ж было либо по группам проекты/права раскидывать, ну или напридумывать шаблонов для запросов.
Нихуя не понял, но есть перегрузки и явная реализация
static object _syncRoot = new object();
void OnEvent(Context ctx)
{
lock(_syncRoot){
if(!_globaContext.HasAnyOtherUser(ctx.BoundResource)){
_globalContext.BindResourceToContext(ctx, ctx.BoundResource);
}
}
}
void OnApplicationComplete(Context ctx){
lock(_syncRoot){
if(_globacContext.HasAnyOtherUser(ctx, ctx.BoundResource)){
_globalContext.FreeResource(ctx);
}
}
}
Ну. Т.е. есть некий ресурс, который шарится между объектами. Когда он никому не нужен - его нужно освободить. Проблема в том, что ресурс - из нативного кода, т.к. GC его может не собрать.
Проблема кода выше - если OnApplicationComplete наступает сразу много где, случается пиздосики. Все потоки начинают пытаться войти в критическую секцию, чтобы попробовать освободить ресурс, а часть потоков - пытается получить его или создать.
В общем. Из-за этого начинается ужас страшный.
И я не знаю как решить эту проблему на самом деле потокобезопасно.
Единственный костыль, что я придумал - вынести это вот выделение ресурса - в собственный поток обработки, который в бесконечном цикле бегает по объектам, если остались объекты, которым какие-то неуправляемые ресурсы нужны - то не удаляем, если не остались - удаляем. А если есть те, кому не дали еще этот ресурс - создадим и дадим. Но это какая-то шляпа если честно. А как иначе - я ХЗ.
static object _syncRoot = new object();
void OnEvent(Context ctx)
{
lock(_syncRoot){
if(!_globaContext.HasAnyOtherUser(ctx.BoundResource)){
_globalContext.BindResourceToContext(ctx, ctx.BoundResource);
}
}
}
void OnApplicationComplete(Context ctx){
lock(_syncRoot){
if(_globacContext.HasAnyOtherUser(ctx, ctx.BoundResource)){
_globalContext.FreeResource(ctx);
}
}
}
Ну. Т.е. есть некий ресурс, который шарится между объектами. Когда он никому не нужен - его нужно освободить. Проблема в том, что ресурс - из нативного кода, т.к. GC его может не собрать.
Проблема кода выше - если OnApplicationComplete наступает сразу много где, случается пиздосики. Все потоки начинают пытаться войти в критическую секцию, чтобы попробовать освободить ресурс, а часть потоков - пытается получить его или создать.
В общем. Из-за этого начинается ужас страшный.
И я не знаю как решить эту проблему на самом деле потокобезопасно.
Единственный костыль, что я придумал - вынести это вот выделение ресурса - в собственный поток обработки, который в бесконечном цикле бегает по объектам, если остались объекты, которым какие-то неуправляемые ресурсы нужны - то не удаляем, если не остались - удаляем. А если есть те, кому не дали еще этот ресурс - создадим и дадим. Но это какая-то шляпа если честно. А как иначе - я ХЗ.
Точнее, 0 1 2
Захват переменной. Решарпер/идея тебе бы сразу по рукам надавали за такое
Потому что майки - пидорасы и не додумались дать возможность явно указать - хочешь захыватывать ты по ссылки или по значению. Нет. Надо спрятать, надо чтобы было неявно, надо, чтобы ты как ебан - делал фактории лямбд.
Округлить сначала?
>>62162
Перевести до целых чисел (умножив на ту точно которая нужна,
в данном случае на 10), это проблема IEEE 754 для всех языков.
Самый лучший способ - не использовать в принципе числа с плавающей точкой.
Либо целые, либо свой тип с фиксированной точкой.
>А как тогда
1) Сравнивать всегда по диапазону с нужной точностью (больше-меньше)
2) Округлять до нужной точности с переводом в целый тип
3) Не использовать float . Очень часто те же бабки, если не подразумевается всяких рассчетов с ними кроме суммирования, просто хранятся в формате int*100.
> А как тогда проверить
У тебя во второй пикче ответ написан.
Взять некое минимальное число, которое будет символизировать предел точности, назвать его греческой буквой Эпсилон.
Или взять искаропки предоставляемый средой https://learn.microsoft.com/ru-ru/dotnet/api/system.double.epsilon?view=net-8.0
Вместо сравнения двух даблов, ты вычитаешь один из другого, берешь абсолютное значение (отбрасываешь минус если есть) и проверяешь больше ли это чем эпсилон? Если это больше эпсилона, то два дабла не равны, иначе равны.
> А фиксированная точка это у каких типов?
Раньше были типы типа денег, с фиксированными двумя разрядами после точки, но в шарпе денежный тип decimal тоже с плавающей. Не знаю, что там имелось ввиду, о чём тот анон говорит.
мимоджун
Просто берешь без задней мысли умножаешь количество денег на 100 и кастишь в int64, имея всегда в уме, что последние две цифры это копейки/центы/пенсы и т.д. В тех редких кейсах когда точность роляет или нужны хитрые бухгалтерские округления, кастишь к decimal, делишь на 100, вычисляешь и потом обратно.
Главное int32 не бери - точно не хватит.
> Или взять искаропки
Искаробочный ЕПС слишком мал. Лучше делать свой, под свои задачи. Пикрелейтед.
>>3001731
> Там XAML, если от него не тошнит, то норм.
Меня тоже от хамла тошнит. Посоветуйте кроссплатформенный UI фреймворк для дотнет фреймворка, чтобы я мог делать фронт пока делаю бэк?
Не знаю где доступно это объясняют. Возможно тут https://en.wikipedia.org/wiki/Round-off_error
Если упрощенно сказать, то при вычитании из большого флоата малого, младшие биты улетят в трубу.
Ну и упрощенно говоря, в пример, Float.Max - 1 миллион == Float.Max. Подумаешь лям туда, лям сюда.
Двойное "подумаешь".
Попытался решить эту проблему так: создал класс CommandCondition, который содержит в себе условие и метод при невыполнении условия; и при создании команды отправляю список этих условий. Если же проходит, то вызывается метод Execute у команды.
Код: https://pastebin.com/d7tnkcVq
Проблема в том, что мне в некоторых командах нужно отсылать параметры, которых нет в CommandContext. Пока что лучше, чем хранить в condition и action массивы object[], ничего не придумал. Что можете посоветовать, чтобы передавать динамические параметры?
Нет ли в этом вопросе проблемы X/Y? Ящитаю, выполнение проверок - это не зона ответственности команд. Ты впихуиваешь невпихуемое. Думой над архитектурой. Тебе нужен синглтон менеджер проверки прав.
Ничем. Мы просто дураки, не нужно с нами водиться, а то и сам отупеешь
Дальше F12 не ухожу, обычно на 2-3 класса вглубь хватает
Современной удобной инфраструктурой. Майки вовремя опомнились и перестали поддерживать легаси.
Шустрый клиент для XMPP но в стиле телеги.
бамп
После ухода авалонии из фонда, я чет сомневаюсь что мягкие хотят честно играть в попенсорс.
Поди те же долбоёбы что написали SerialPort
Не нашёл в доке. Да я тупой, будьте толерантны. Спасибо!
Вот как мне сделать что-то типа такого с тем что собирается?
Типа, чтобы была папка с экзешниками типа "корень". Подпапка bin в которой лежат всякие dll и прочие штуки.
Ну и data - для всяких ресурсов приложения(звуки там, картиночки, шрифты, ну вы поняли).
Типа да. Я знаю, что я могу сделать app.exe типа просто неким хостом, собрать дотнетом в единый исполняемый файл, а потом лезть в папку bin и data.
Но я бы хотел, чтобы типа мне не нужно было ебаться со всем этим поздним связыванием и прочим, а просто чтобы запустил, оно собралось, я кайфую. А все это позднее связывание - заставляет так изъебываться на самом деле с тем как проект собирать, копировать куда-то выходные dll и прочее-прочее.
Пишешь таргет в мсбилде на перенос дллок, в поиск путей с дллками добавляешь свой путь
Чë, испугались?
А это та самая авалония? Говнище полное. До сих пор на Ето.Формсах гуи ебошу и кайфую. Никакого тебе хмл-говна. Взял и описал форму прямо в конструкторе, красивым декларативным способом, в который шарп нынче научился.
Ничего не имею против авалонии кроме шрифтов под виндой
Какое отношение они имеют к мелкософту? (ну кроме того что мс решили родить мауи, а не взять авалонию под крыло - что лично я осуждаю, но что подчеркивает что мс до авалонии дела нет. Дело есть у джетбраинс, но они не мелкософт)
>красивым декларативным способом
Это то что раньше в дедовские времена студия сама генерила от вкидывания контролов
Что тут красивого
Красиво это jetpack compose
Ну майки вроде как заценили как бустанулся дотнет при переходе на попенсурс модель, но это не отменяет вероятности прихода очередного эффективного который решит, что нужно возвращаться к корням.
Ну и опять же у майрософта столько бабок, что они вполне могут начать косплеить гугол и однажды сказать что, "ребяна, нахуй все, нам надоело, в жопу ваш дотнет" и слить его куда-нибудь, а то и вовсе закрыть.
Там же вроде MIT, то есть последняя версия все равно останется у комьюнити, не? Понятно что потом могут создавать всякие трудности типа у нас названия API закопирайчены, но с высокой вероятностью пойдут нахуй или просто будет переименовано.
Они уже начали EEE, там у линуксоидов что-то с хотрелоадом. Ой, ну такая же мелочь, казалось бы? Ну наверное надо идти на винду, на правильную IDE, где все работает правильно.
Какие еще подводные там есть, хз.
Начал некоторые проекты, почитал нытье на эту тему и решил переписать. Сами шарпы, конечно, не виноваты, продукт годный, но не хотелось бы играть в квази-опенсорс
> Какие еще подводные там есть, хз.
Есть один, который никто почему-то не замечает. Дебаггер дотнета проприетарный и работает только в студии и вскоде (хоть и на линуксе).
Спасибо за инфу.
Есть задача, которая асинхронно ждет какое-то время, а потом проверяет состояние булевой переменной, которое меняется извне. Зачем мне использовать токен отмены, который к тому же и диспозить надо, когда я могу использовать инвок к булевому свойству?
Или же токен отмены используют в случаях, когда запросы состояния возникают очень часто?
Можешь подробнее описать проблему? Ничего не понятно.
Тебе надо распарсить строкове значение в int?
Опиши какие данные поступают из файла и что в итоге ты ожидаешь. Опиши какое исключение возникает.
Это пока тебе не понадобилось сделать сложный интерфейс.
>Взял и описал форму прямо в конструкторе
В wpf тоже самое. Может перетягивать контролы и менять их свойства в окошке свойств.
Ну а на скрине говнище ебаное, прибитое гвоздями. Любая задача чуть сложнее интерфейса калькулятора и ты закопался, либо просто не стал делать.
А ты попробуй в 10 методах, да по уровням использовать свою переменную - вот тогда и узнаешь.
>Они уже начали EEE, там у линуксоидов что-то с хотрелоадом.
Это как раз таки не ЕЕЕ, а то самое "нам надоело - ебитесь сами". Они по той же причине выпилили и на маках свою IDE.
Там на самом деле много такого в духе "мы вам итак кросплатформенность завезли, но мы не подписывались совсем все дорабатывать". Та же System.IO крайне ограничена при работе с файловой системой линукса, а официального ничего особо и не предвидится. Есть только mono.posix, который х.з. уже сколько лет в состоянии rc и не собирается из него выходить.
Проблема в том, что даже несмотря на то, что там все под MIT, если майки реально забьют на шарп, то если его не возьмет под крыло какой-нибудь "фоундэйшен", то он просто загнется (собственно как и любая другая платформа)
> Любая задача чуть сложнее интерфейса калькулятора и ты закопался, либо просто не стал делать.
Этот фреймворк делался как интерфейс для специфичного дизайнерского софта, которым пользуются в основном ювелиры. (Rhinoceros 3D - 3D computer graphics and computer-aided design (CAD) application) И до сих пор тот софт на ето.формсах работает.
И никто там не закапывается.
Сначала охватили аудиторию, а потом начали закручивать все везде, кроме винды. Ну да, устали они.
Заработать репутацию очень сложно, потерять очень легко.
А начали они вообще с анально вендорлокнутого виндой нетФреймворка
Я ещё не видел ни одного языка, где хотя бы на одной системе хот релоад работал как надо.
Всегда отключаю по возможности, потому что нет никаких гарантий, что код после хот релоада ведёт себя так же, как после колд.
вообще то да. Как захочешь сделать кастомный контрол так сразу поймешь
Но вообще тупо показывать "вон это написано на этом значит это хорошо". Потому что при должном усердии на всем можно написать гуи.
а ето фомс описание выше - ну это же реально древность. так в QT описывают или дизайнер винформс сам пишет.
Хамл не особо лучше, но все же он изначально задуман как lookless
А тут просто кроссплатформенный винформс да еще с описанием ручками
новомодно это jetpack compose
там тоже кодом. но есть НЮАНСИЩЕ
Для зумеров туда завезли хамл и мввм с обсервабле коллекшонами. А мне и дидовский метод пойдёт, я дед.
> захочешь сделать кастомный контрол так сразу
dotnet new etofile -p
>Для зумеров туда
когда возникла технология зумеры еще под столк пешком ходили
>dotnet new etofile -p
и че дальше? магическим образом возникнет магический контрол? ню ню
> дидовский метод пойдёт, я дед
каждому свое. у каждого свои радости. Я вот не использую EF и гит (а божественный меркуриал) и мне норм.
В авалонии тоже можно описывать форму прям кодом, XAML продвигается для аналитиков и дизайнеров, чтобы не тыкали программистов цвет кнопки поменять
Говорилось что фишка XAML в том чтобы мимокроки могли делать чисто косметические изменения в форме без программистов, хз где есть такое
>а божественный меркуриал
Как же я грустил когда пришлось окончательно поменять меркуриал на гит. Хотя я уже и привык, но все равно иногда так хочется.
А я в банке пишу системный (ну почти) софт. Я доволен.
>которым пользуются в основном ювелиры
Там диапазон от ювелирки до архитектуры. Я знаю про рино. Я в нем работал долгое время, собсно я так в шарп вкатился.
Основная претензия к этой программе в том, что у нее внезапно устаревший интерфейс. Я много кого хотел пересадить на рино, ибо в России он не очень популярен, но все смотрели на скриношоты UI, говорили фу какой кал и скачивали фьюжин (несмотря на то, что это кал по функционалу). А после выхода пластисити можно рино закапывать. На ней мамоны по типу меня еще посидят какое-то время, потому что привыкли, но притока новых пользователей не будет.
>И никто там не закапывается.
Когда я слышу о винформсах, то обычно речь идеть об эгоизме самих разработчиков, которым лень чет там пилить, и естественно под эту лень они выдумывают массу причин. В итоге разработчики "не закапываются", потому что при возникновении проблемы они эту проблему шлют нахуй, а пользователю это просто не интересно и он идет искать что-то еще.
> устаревший интерфейс
Интерфейс устаревший у рино, и в самом етоформсе по умолчанию не включены темы, но они есть. Авторы сами любители нативного лука, поэтому темы не включены искаропки.
> Когда я слышу о винформсах
Там платформонезависимые окна, когда ты их описываешь, у них свой набор виджетов, без визуализации. Визуализацией занимаются отдельные пакеты-адаптеры, имеющие префикс eto.platform, таким образом, винформсы и WPF в рамках етоформс - это отдельные платформы. Ты можешь сделать приложение, которое на выходе будет отрисовано WPF, причём при создании шаблона по умолчанию именно адаптер WPF создаётся для винды. Так же авторами фреймворка учитывается, что у разных платформ есть свои отдельные виджеты и свойства, и для этого есть возможность пробросить через платформенный адаптер нативные колбэки и хэндлеры изнутри наружу и наоборот.
Да, название фремворка запутывающее, как будто ты поверх винформс должен работать, но это не так.
Точно так же работает и хамарин и мауи, но всё не описывается кодом
Причем разве это код вообще. Он не императивный
Просто точно такой же код может написать дизайнер идешки
Он не императивный
В MVU(I) подходах он императивный. Но это не про шарп
я хочу донести что показанное "смотрите как можно описывать уи в ето.формс" по факту просто является обычным кодом (с упором на некоторые фичи шарпа) описания как деды описывали, только за них дизайнер писал.
И что как бы на смену этому и пришел хамл (ну чтобы кодом не описывать)
так что это не будущее. это прошлое.
далее работают что етоформс, что замарин по одному принципу, но первый описывает кодом, а второй хамлом. Что лучше? да 2 стороны одного говна
А вот реально другое - MVU подход. там уи описывается кодом, но, в зависимости от возможностей языка, делается это с некоторой долей императивности
То есть сам код является не только описанием "что во что вложенно + аттрибуты), а именно выполняемым
Для понимания задача - по флагу показать кнопку или картинку. В WPF это решается через ContentControl
а императивно буквально так
if (showImage){
Image
}else{
Button
}
ну то есть самый обычный код.
я не говорю что это лучше. Это просто по другому. Но это хотя бы не из древности
Я тебе скинул скрин 5 секунд в гугле по слову "императивность", ознакомься.
То что у тебя своё определение императивности - делает твои посты нечитаемыми.
> на смену этому и пришел хамл
В етоформс есть хамл.
> А вот реально другое
> задача - по флагу показать кнопку или картинку
> а императивно буквально так
В етоформсах тоже именно так. Контентом топлевельных виджетов (окон) могут быть наследники контейнеров (лэйауты, таблицы) в них элементы контейнера содержат наследников контрол-виджетов. Таким образом можно на лету менять кнопку и картинку по нажатию чекбокса.
Но я всё ещё не понимаю, причем тут императивность? Почему ты так оббазвордился императивностью? В шарп завезли декларативность, может ты всё это время путал императивность с декларативностью?
хамл, жсон и т.п. - это декларативные языки описания структур данных. В шарп завезли инициализаторы, которые по сути именно делают декларативное описание создаваемого инстанса. Делаешь несколько вложенных инициализаторов и получаешь функционально те же яйца, что и хамл, только в профиль.
И вообще, в этом коде у тебя смешана логика и данные, что в современных гайдах не приветствуется.
> if (showImage){
> Image
> }else{
> Button
> }
Правильно по зумерски ебануть во вьюшку оба элемента и прибиндить их видимость к чекед-свойству вьюмодели которое прибиндить к чекед свойству чек-элемента. Не?
>То что у тебя своё определение императивности
это у тебя какое то свое. я тебе описал ИМЕННО ТО ЧТО В ГУГЛЕ и вообще во всем мире
то есть инструкции описывающие UI ВЫПОЛНЯЮТСЯ буквально построчно сверху вниз
А НЕ ПРОСТО ОПИСЫВАЕТСЯ иерархическая структура контролов и их аттрибутов
>причем тут императивность? Почему ты так оббазвордился императивностью?
не причем вовсе. просто упомянул что то, что вы принесли - старое говно мамонта в плане описания UI, даже старее хамла и "вот если бы что то новое типа.." а там и речь зашла о новых подходах.
>Таким образом можно на лету менять кнопку и картинку по нажатию чекбокса.
Везде можно. В любом подходе описания уи. ето.формс не уникален, а один из...да всех в общем то.
>хамл, жсон и т.п. - это декларативные языки описания структур данных
Да кто ж спорит. хамл это то же самое описание кода в другом виде. Вот только хамл описание позволяет визуальный дизайнер запилить. Даже винформс позволяет запилить дизайн из кода. А что там с ето.формс? хамл я пишу руками, но вот на райдер не перехожу из за того что там дизайнера нет. Да и в хамл я могу руками писать гуи - никто ж не запрещает. и дизайнер будет.
Ну и основная претензия к этому всему - крайняя ограниченность кастомизации в угоду кроссплатформе и нативности гуи на конечной платформе.
>>70372
>у тебя смешана логика и данные
нет не смешана. не путай логику модели (или даже вьюмоделей) и логику UI
>прибиндить их видимость к чекед-свойству вьюмодели которое прибиндить к чекед свойству чек-элемента. Не?
закат солнца вручную. Логика элемента то обрабатывается хоть он и не виден (только логику связанную с рисованием движок может скипнуть, а все что наворотил пользователь - нет)
Попробовал.
Эта срань работает криво. Если путь для поиска пути задавать относительный, то в случае запуска в виде демона/сервиса - приложуха не стартует(
Эх.
Мдя...
Использую абсолютные пути. Узнать из какого места произошел запуск нет никаких проблем
> Использую абсолютные пути
Так а как я узнаю абсолютные пути, если приложуху пользователь куда хочешь может положить по желанию?
А без этого - хостовый процесс - не сможет запустить уже мой проект, чтобы я там что-то подгружать начал и разрулил если надо пути.
Чел. Я же говорю о случае, если ты запускаешь свой проект из другого места.
Вот допустим, если я захочу свою хуйню запускать как виндовый сервис, она будет дергаться из system32. И тогда вся эта срань по пизде пойдет, если путь до папки с dll'ками полностью не прописать.
А прописывать полностью - бред, потому что пользователь, который скачал и себе хочет установить - не .NET-хуй, и ему разбираться, куда там че прописать не всралось, а положить скачанное он может в любую папку.
Ну да ладно.
Ещё раз повторяю, код никак не привязан к месту из которого вызывается всё что ему нужно это что бы дира dlls была в дире где лежит основная дллка, всё, не важно больше ничего
Для хостового процесса .NET, который ищет откуда брать сборки - важно.
Если указан относительный путь где искать сборки - оно не разруливается.
Вот ишью с этим https://github.com/dotnet/runtime/issues/72571
Если не так, показывай по шагам, че делаешь.
>>70963
И ты показывай. А то просто постишь скриншот, хуй знает чего с каким-то выводом в консоль.
Не хочешь верить значит иди нахуй. Я даже заебался и как сервис в винду запульнул этот экзешник.
У всех эта хуйня работает с тем же цефом для выбора x32|x64 либ, а у тебя не работает, во дела то!
Заебал ты меня, я всё надеялся что ты в гугл пойдёшь и первой ссылкой увидишь AppDomain.CurrentDomain.AssemblyResolve в связке с Assembly.GetExecutingAssembly().Location
Но видимо ты решил не гуглить совсем
Чел. Это позднее связывание. Я про него еще в первом посте написал.
> . Я знаю, что я могу сделать app.exe типа просто неким хостом, собрать дотнетом в единый исполняемый файл, а потом лезть в папку bin и data.
И я написал, что не хочу этого делать. Я хочу чтобы у меня все dll - были во время разработки - как обычно через референсы указаны, чтобы я мог просто дергать их как человек. Но после разработки - переложить их в папочку bin/libs/dlls, чтобы более чистый вид был. Можно конечно для этих целей собирать все в один экзешник, но опять же по памяти - там начинается хуерга что как сервис оно стартует хуево(оч долго, и на том же линуксе систимде - начинал вонять по этому поводу).
Короче. Ты мне напиздел получается.
Так и работает, дурачина. Я руками сейчас беру и перекладываю дллки в dlls после билда, до этого они беруться из рута.
Никаких отличий в использовании вообще нет, просто добавляется хук на поиск.
В проекте нет абсолютно никаких отличий от стока кроме ручного переноса дллок если нужно и доп резолвера
В доке прямо написано что вызывается когда не удалось найти дллку в стандатрных местах
И я заебался на середине затирать юзернейм, так что можешь в телегу написать если подгорело
>>71004
>>70997
Хм. Ладно.
Признаю. Был не прав. Косо пробежался по первому куску кода и не заметил, что тут какой-то обработчик события накидывается. Подумал, что просто загружаются сборки из папки.
В свое оправдание - в нормальном .Net Framework - такой ебельди делать не надо было. Просто в config дописываешь <probing privatePath="bin"/> и как человек радуешься.
Ой, да не надо. Единственный минус фреймворка, это то, что из-за его раздутости - были дублирующие штуки и приходилось догадываться, из какого пространства имен нужное тебе.
В остальном - это было лучшее в плане девелоперского экспириенса, что вообще возможно. Я только из-за него этим программированием и занялся.
Опять же. Вот пример как оно делалось в те времена.
Все. Никаких там ресолверов и прочего. Просто указал подпапку и радуешься.
>Вот допустим, если я захочу свою хуйню запускать как виндовый сервис
Тогда тебе должно быть лихо похуй, что там у тебя внутри каталога с приложением твориться, максимум конфиги в отдельный каталог положить, если ты не сподобился вынести их в консул или еще куда-нибудь наружу.
Мне и было похуй, пока пользователи не начали ругаться, дескать, ря, много дллок, хуй найдешь нужный экзешник, говно сделал, пидорас, уууу, уууу, уууууу
Извини, а нахуй юзеры лезут в папку с софтом? Всё что они должны видеть это инсталлер и ярлыки на рабочем столе
>Ехал Грека через реку, видит Грека в реке рак, сунул Грека руку в реку, рак за руку Греку цап.
Есть набор ключевых слов
>Грека, рак
Грубо говоря мне нужно подсветить ключевые слова. Я должен разбить строку по этим ключевым словам и каждому отрезку присвоить соответствующий стиль текста. Но я не понимаю как разбить строку так, чтобы я знал что и где находится. Для примера несколько способов:
1. Если я воспользуюсь методом string.Split, то я разобью строку на массив нонейм отрезков, при этом я не знаю в каких элементах содержится слово "Грека" или "рак".
2. Или взять Regex
>(?:Грека|рак)
Я получу ключевые слова, но потеряю отрезки текста, не являющимися ключевыми словами. А мне надо разбить предложение, а затем снова собрать.
3. Самый контролируемый вариант получается при использовании метода string.IndexOf, когда я узнаю индекс вхождения искомой строки. Но у меня чувство, что при таком способе каждый раз я изобретаю велосипед.
Начнём с того что в результатах регулярки есть индексы символов в строке по которым попадание
Ааааа, спасибо. Точно, что-то такое видел.
Ну, опять же, мне вот лень было делать хуевину чтобы задавать настройки, все настройки - лежат в appsettings.json. Отдельно задачу - сделать возможность настраивать все это из UI тоже никто не ставил.
Так что периодически - надо лазить.
Я оправдываю свою лень - тем что в линуксе вон никто не выебывается, идут в /etc/conf и всем ок, так что и тут потерпят)
так то линукс. там народ привык к мучениям и пердолингу
А тут пока найдешь где оно в профиле в этих роаминг локал хрен разберешь в чем разница и куда вообще идти. Умные люди делают менюшку в софтине которая откроет блокнот с настройками.
но ты мучай людей, мучай.
Ну, я примерно такое и собирался сделать.
В первом посте скриншотик того как хотелось бы >>67457
>>71417
> Умные люди делают менюшку в софтине которая откроет блокнот с настройками.
Нууууу. У меня таки софтина - это скорее сервисная хуйня для работы с большим спектром железяк. Обычно работает как демон. И обычно, когда у клиента новые железяки появляются, с которыми с первого раза что-то не получилось - ему надо залезть в папку и поставить нужный флажок, посмотреть, помогло ли, если помогло - радоваться, если не помогло - крыть меня хуями, чтобы я выяснил в чем дело, добавил новый флажок (потому что вся эта хурма у меня за флажками, чтобы в случае если оно только хуже сделает - можно было тупо отключить), и потом он новый флажок поставит и все заработает. Такие вот дела. Переработать это все чтобы было по человечески - никто времени не дает. Я уже, если честно, сам не помню за что там все флажки и настройки отвечают, лул.
В теории - да. На практике - ни разу вот прям чтобы сжечь не было, самый хуевый случай это как раз бесконечный ребут.
>Ето-господин не мог слиться
однако он слился ибо читает ЖОПОЙ
и ЖОПОЙ же думает
я не говорил что авалония императивная
я сказал что есть И императивные подходы к выражению UI, а не только декларативные
и императивный подход НЕ ОТМЕНЯЕТ биндинги, шавка ты етовформовская бестолковая и там тоже можно вот так через визибилити сделать.
Разница декларативного UI и императивного в том что в императивном случае ТАМ ВЫПОЛНЯЕТСЯ КОД при построении UI. И если в декларативном твой код спрятан в контролы, биндинги, code-behind, то в императивном стиле он прямо описывает UI ВЫПОЛНЯЯСЬ!!!!
То есть код не является описанием структурности, использую которую потом движок построит UI, а код является самим кодом построения UI. Пошло выполнение if по ветке фалсе - и элемент просто не появился в визуальном дереве. Ключевое слово - пошло выполнение.
ты жопой прочитал. не разобрался о чем речь, но жопа твоя запылала
и ты притащил решение...ТАКОЕ ЖЕ как оно делается в авалонии, в впф и даже в винформс с биндингами лол. Что нового ты показал? ты показал СТАНДАРТНОЕ решение и кичишься этим.
>Нет логики в элементе
Кто сказал? А если это мой контрол где в code-behind может быть сколь угодно сложная логика, подписки там всякие и тому подобное. Я могу спокойно подписаться на INPC соурса (и конечно реагировать на события) и меня совсем не радует разбираться виден ли мой контрол или нет.
хоть это и оффтоп ибо про императивность я просто упомянул, но все же покажу что такое MVU подход
смотрим (там правда котлин, но не суть)
https://pastebin.com/UNkWhr83
смотри описание структуры - оно очень похоже на описание твоего ето.формс и вообще просто описание кодом
но по факту - все это МЕТОДЫ, которые буквально вызываются и выполняются
и там второй пример табконтрол
никакого биндинга типа ItemSource (хотя конечно делается как 2 пальца в кастомных контролах)
поскольку код выполняется, то вкладки создаются
tabs.forEachIndexed
потому что в общем то это не табконтрол, а просто колонка, где ты сам рисуешь
и ты можешь конечно обернуть все это в функцию и и назвать ее TabControl
и все это не отменяет биндинги вьюмодели и так далее. Просто другой подход - при изменении вьюмодели не идет обновление по биндингам, а идет тотальное "изменилось там где вы читаете, перевыполните себя".
но это котлин, а котлин - это мощь в выразительном плане, поэтому может оперировать методами и скоупами
В других же языках приходится делать контролы классы и тогда код уплывает в метод этого класса, но принцип остается тот же - следим за местами обновления стейта и просим контролы себя обновить.
пример swift combine https://pastebin.com/Xcqv8Rj2
там тоже есть if
Шарп тоже так может как свифт, что то даже в MAUI делали такое. https://github.com/dotnet/maui/discussions/12820
И даже дебильное шарповское new можно убрать через static using
И вот это реально другой подход со своими плюшками и недостатками. А ты показываешь древность и радости полные штаны.
хоть это и оффтоп ибо про императивность я просто упомянул, но все же покажу что такое MVU подход
смотрим (там правда котлин, но не суть)
https://pastebin.com/UNkWhr83
смотри описание структуры - оно очень похоже на описание твоего ето.формс и вообще просто описание кодом
но по факту - все это МЕТОДЫ, которые буквально вызываются и выполняются
и там второй пример табконтрол
никакого биндинга типа ItemSource (хотя конечно делается как 2 пальца в кастомных контролах)
поскольку код выполняется, то вкладки создаются
tabs.forEachIndexed
потому что в общем то это не табконтрол, а просто колонка, где ты сам рисуешь
и ты можешь конечно обернуть все это в функцию и и назвать ее TabControl
и все это не отменяет биндинги вьюмодели и так далее. Просто другой подход - при изменении вьюмодели не идет обновление по биндингам, а идет тотальное "изменилось там где вы читаете, перевыполните себя".
но это котлин, а котлин - это мощь в выразительном плане, поэтому может оперировать методами и скоупами
В других же языках приходится делать контролы классы и тогда код уплывает в метод этого класса, но принцип остается тот же - следим за местами обновления стейта и просим контролы себя обновить.
пример swift combine https://pastebin.com/Xcqv8Rj2
там тоже есть if
Шарп тоже так может как свифт, что то даже в MAUI делали такое. https://github.com/dotnet/maui/discussions/12820
И даже дебильное шарповское new можно убрать через static using
И вот это реально другой подход со своими плюшками и недостатками. А ты показываешь древность и радости полные штаны.
>так то линукс. там народ привык к мучениям и пердолингу
Хуйню не неси. Регулярно лезу в конфиги графических программ на шиндовс. А в играх так вообще норма менять настройки через конфиг, потому что некоторые недоступны через графический интерфейс.
>Регулярно лезу в конфиги графических программ на шиндовс
твои личные страдания. обычно виндософт таким не страдает
игры вообще исключение
даже вот оно вроде живо
https://github.com/adospace/reactorui-maui
поверх мауи, который суть хамарин, который по той же фигне делает что и ето.формс
но где такое в ето.формс?
>formatProvider: CultureInfo.InvariantCulture
И создаю тестовые логи данных различных типов (пикрил 2). И получаю результат (пикрил 3). Часть действительно в InvariantCulture, всем остальным записям насрать.
Еще хуже, когда выставляю CurrentCulture (пикрил 4), тут даже не соблюдаются правила культуры. Например разделитель дробной части через запятую, но итемы почему-то тоже через запятую, хотя там должна стоять точка с запятой.
Что происходит?
>обычно
С чего ты вязл, что обычно? Может это твой случай уникальный. Любой более или менее сложный софт требует правки конфигов из файлов. К примеру вижуал студия.
опять на дваче капчу ушатали, как будто тут народу по сотне тысяч человек в день.
> Кто сказал? А если это мой контрол где в code-behind может быть сколь угодно сложная логика, подписки там всякие и тому подобное.
Если там такое будет, мы тебе не перезвоним.
>>71486
> дебильное шарповское
> котлин
> котлин
Долго жаваблядок держался, но всё таки мы его вытащили на чистую воду. Репортим.
> но где такое в ето.формс?
Мне это не нужно.
У меня паттерн MV, в нём отброшено всё лишнее. Есть только модель и только вьюшка. Модель ничего не знает о вьюшке, вьюшка знает о модели. Всё работает идеально, как швейцарские часы, даже объяснять лень.
>К примеру вижуал студия.
ни разу не лазил в текстовые конфиги студии. Не знаю зачем это делать в принципе.
>>71797
>Если там такое будет, мы тебе не перезвоним.
так будет в любом контроле. Даже листобокс реагирует на изменения, просто дело до отрисовки не доходит ибо контрол не виден. Но подписки отлично работают пожирая процессорное время и оперативу.
В кастомных контролах заморачиваться о "а вдруг я collapsed заморачиваться просто нет смысла"
>Долго жаваблядок держался
ты вельми ДУРАЧОК. я тыщу раз говорил что пишу на шарпе (основной доход), но под андроид пишу на котлине в силу нативности подхода. И котлин обладает огромной выразительной мощью, что в шарпе и не снилась, но отвратительным рантаймом.
>>71802
>Мне это не нужно.
ну и срать на тебя. поверь, всем срать на твои личные замуты.
просто в следующий раз когда будешь чем то кичиться - то не подходом 30 летней давности плиз.
>У меня паттерн MV
а те кто пишут хамлом у них не так? что ты бред несешь ленивец
нихрена нового ты не притащил.
плюсы ето.формс - кроссплатформа
минусы - ограниченность нативными контролами + как ты сам показал, убогое выражение кодом "как деды писали"
Итак, у моего приложения текущая культура вот такая:
>CultureInfo.CurrentCulture: "ru-RU"
Если я глобально, для приложения ставлю "en-US":
>CultureInfo.CurrentCulture = new CultureInfo("en-US");
то конвертация во всех случаях выглядит хотя бы адекватно,
>Test of 'Point' data: "100.8,5"
>Test of 'Array' data: [90.3, 70.8, 5, 34]
>Test of 'PointCollection' data: ["10.4,30.5", "25.5,17.9", "9.3,100.7"]
но тогда я сру себе в приложение, я не могу с этим дальше работать.
Если же я в конфигурации логгера устанавливаю
>formatProvider: CultureInfo.CurrentCulture
то при конвертации массивов, элементы по прежнему перечисляются через запятую как будто бы все еще стоит "en-US", хотя сами числа используют формат "ru-RU". Получается бредик:
>[90,3, 70,8, 5, 34]
Серилог виноват? Как это пофиксить?
Я тебе для примера написал. Не для всех софтов есть подобные решения.
Ну так ты хотя бы просто конфиги в отдельный каталог Config вынеси, тогд пользователю не придется их искать среди кучи dll-ок. Он будет заходить в каталог приложухи и сразу видеть куда ему дальше лезть нужно.
Конфиги в директории с приложением должны быть в состоянии ридонли.
А вот пользовательские редактируемые конфиги должны быть в AppData. И если пользователь случайно повредил их, либо нажал кнопочку "Reset to Default", то оригинальные файлы из папки приложением копируются в AppData.
Если "все яйца хранить в одной корзине" тобишь хранить редактируемые конфиги в папке с приложением, то их поломка приведет к поломке приложения, пока пользователь не переустановит его заново.
>А вот пользовательские редактируемые конфиги должны быть в AppData.
Ну че-ел. Так-то если дальше рассуждать, то конфигов на диске не должно быть вообще. Они должны лежать где-нибудь в энвайронменте/БД/консуле/жопе твоей мамки и т.д. Плюс должен быть прикручен механизм бэкапа/восстановления и прочая красота и свистоперделки. Плюс это все должно быть в контейнерах, контейнеры в кубере, утка в яйце и т.д.
Чел же прямо сказал, что ресурсов на рефакторинг у него нет, а править конфиги пользователям надо, поэтому они и лезут. Я и посоветовал, чтобы хоть немного упростить им жизнь - вынести конфиги в отдельный каталог, т.к. это делается буквально несколькими строчками кода.
>>71918
>пока пользователь не переустановит его заново.
Во вторых если программа предполагает модель работы как фоновый сервис, то она в принципе должна подчиняться принципу, что её можно в любой момент снести и накатить заново.
Это я приблизительно понял.
Для сложных типов использует ToString(), который зависит от текущей культуры приложения. Но вот примитивные типы он конвертирует используя культуру, установленную в конфиге.
Проблема в том, что символ разделители элементов списка как будто захардкожен и всегда через запятую.
>[90,3, 70,8, 5, 34]
Я не знаю как это пофиксить. Я не могу использовать InvarantCulture в конфиге, потмуо что не будет работать адекватно ToString(), и не могу использовать CurrentCulture, потому что разделители итемов списка "сливаются" с разделителями дробной части чисел.
Конечно, я могу различить разделитель дробной части "," от разделителя итемов ", " по наличию пробела, но это какая-то дичь.
ну что он там использует для сериализации структур? жсон же (сам я любитель нлог)
ну а что у нас там в стандарте жсон?
>>71922
Позырь вот тут:
https://blog.revolution.com.br/2023/07/17/log-formatters-in-c/
Конкретно раздел:
Creating a custom formatter
>Я щас это изучаю, но боюсь, что это имеет отношение как раз к форматированию элементов, а влиять на формат вывода списков я не смогу.
Там просто как раз кастомный форматтер делается, плюс мелькает параметр ListSeparator, так что я думаю если даже это не то, то близко.
На локалхосте.
Да там ссаный джисон конфигуратор, а я его не люблю.
Можно перед идентификатором параметра поставить символ собаки
>if (_log.IsDebug()) { _log.Debug("Test of 'Point' data: {@p}", new Point(100.8, 5)); }
Тогда элемент разбивается вот на такое:
>Test of 'Point' data: Point { X: 100.8, Y: 5 }
Т.е. сериализуется элемент. И если это какой нибудь Rect, то мы получаем вот это:
>Test of 'Rect' data: Rect { IsEmpty: False, Location: Point { X: 0, Y: 0 }, Size: Size { IsEmpty: False, Width: 30, Height: 49 }, X: 0, Y: 0, Width: 30, Height: 49, Left: 0, Top: 0, Right: 30, Bottom: 49, TopLeft: Point { X: 0, Y: 0 }, TopRight: Point { X: 30, Y: 0 }, BottomLeft: Point { X: 0, Y: 49 }, BottomRight: Point { X: 30, Y: 49 } }
Вместо этого:
>Test of 'Rect' data: "0;0;30;49"
Смотрел IFormatProvider, но он конвертирует конкретно итем.
ITextFormater отвечает за сборку строки лога целиком.
Если про конкретно где - то ни скажу.
Если про тех часть - контейнеры на альпайн, без рантайма. Сравнение показало, что self contained с обрезкой неиспользуемого выходит экономнее, а это таки оказалось важно, когда контейнеров куча.
В Golang, в Java или в C#?
Где вероятность найти работу выше для джуна?
Платиновый вопрос - как совладать с шифрованием в бэкенде?
В тырнетах советуют архитектурно это вынести это на уровень репозитория, но как мне вынести это в репозиторий если он работает с моделью в которой у меня шифрованные байт массивы. Ладно, это можно вынести на уровень сервиса, ок.
Вопрос два - что там с производительностью? Мне нужно сделать поиск, сортировку и фильтрацию. Если без шифрования я мог сделать это на уровне бд (энтити запросом), то сейчас мне получается нужно доставать все эти данные, разшифровать и уже делать то что я хочу, но мне интуитивно (да, замеры я никакие не делал) кажется это будет явно более накладно делать на уровне приложения чем на уровне базы.
Как вообще происходит вот эта сортировка/фильтрация в больших интернет магазинах к примеру? У них дохулион товаров, и допустим юзер юзает какие-то фильтра на них, я не верю что фильтра в этот момент применяются к абсолютно всем товарам в базе на каждый запрос каждого юзера. Сервер делает какую-то индексацию во временные таблицы раз в сутки ночью и потом на запросы берет данные оттуда?
Где-то можно почитать как это считается правильно реализовать роботу с шифрованными данными + большими объемами?
>как совладать с шифрованием в бэкенде?
Нахуй не нужно. Просто прячешь все за межсетевой экран и дальше уже не твоя забота. Максимум хэшированием и соленьем сенситив инфы заморачиваешься и все.
Почему не нужно?
А если у меня такой проект/такое требование?
А если внезапный слив данных?
И что ты имел ввиду здесь под сетевым экраном? Локальную сеть для бд и сервера?
> Мне нужно сделать поиск, сортировку и фильтрацию
Вводи сурогаты, по которым можно произвести этот самый поиск-соритровку-фильтрацию, либо не шифруй то, по чему искать-фильтровать-сортировать собрался.
Как-бы шифровать надо чувствительные данные: пароли, эмейлы, логины, телебоны, номера карт и т.д., что и так не должно палиться по хорошему.
Про производительность. Если ты не собираешься базу на 100500 миллионов записей доставать и дефишвровать-шифровать, то разницы значительной ты не заметишь.
> Как вообще происходит вот эта сортировка/фильтрация в больших интернет магазинах к примеру
В кеш скдадывают и отдают из кеша. Чего нет в кеше - лезут в БД и кладут потом в кеш. Максимум - делается индекс. Потому что все уже наелись этих ебанутых БД с 100500 миллионами таблиц и гигатоннами логики в триггерах и хранимках. БД - просто хранилище. Если надо быстрее - выкидываем и берем ту что быстрее.
Опять - никто не шифрует в интернет магазине товары, нахуй. Это не то что представляет ценность. Все равно, что шифровать блоги в БД, нахуй. ЗАЧЕМ, блядь? Вот зачем? Чтобы хвастаться, что у тебя все зашифровано?
Скорее всего он спросил это во всех тематических тредах. Щас ждет в каком треде ему наиболее любезно ответят.
Ты опоздал лет на 10
> Поясните за бардак в культуре. Вот я ставлю в серилоге (пикрил 1)
> Что происходит?
Серивлог происходит.
Серивлог лютый кал. Возьми лучше Nlog, хватит срать себе в логи.
Nlog гибок в настройке, на 3 головы выше и точно так же умеет в структурное логирование.
>>73570
>Вводи сурогаты, по которым можно произвести этот самый поиск-соритровку-фильтрацию.
Можно поподробнее примеры как это делать?
>Как-бы шифровать надо чувствительные данные: пароли, эмейлы, логины, телебоны, номера карт и т.д., что и так не должно палиться по хорошему.
Уже само собой есть.
>Опять - никто не шифрует в интернет магазине товары, нахуй. Это не то что представляет ценность. Все равно, что шифровать блоги в БД, нахуй. ЗАЧЕМ, блядь? Вот зачем? Чтобы хвастаться, что у тебя все зашифровано?
Понятное дело что если данные логически открыты для пользователей, то нахуя их шифровать в базе. Вот только у меня проект такой что в нем есть доступ только для авторизованных пользователей и у стороннего мимокрока вообще никакого доступа быть не должно как и в принципе открытых данных.
> или есть для этого какие-то специальные хранилища в котором выше производительность?
Да, есть, файловая система называется
> Можно поподробнее примеры как это делать?
Вот у тебя есть колонка: Любимый дилдак.
Там значения: Dragon Super XXXL, Horse Master XL, AssCracker 9000
Эти данные ты хочешь зашифровать.
Тогда, ты берешь и добавляешь сурогат FavItemFilterValue, FavItemSortValue и т.д., для которых сохраняется порядок, возможность отфильртовать и прочее.
И свои операции - ты производишь уже по этому сурогату.
Вся задача сводится к тому, чтобы написать функцию, которая будет оригинальное значение в некий хеш с нужными свойствами переводить.
Пример такого подхода есть в реализации опенвики.
> Вся задача сводится к тому, чтобы написать функцию, которая будет оригинальное значение в некий хеш с нужными свойствами переводить.
Как то так?
Шарпаны, а вызывать асинхронные методы в конструкторе (через Task.Run например, с последующим ожиданием выполнения) - это сильно зашквар?
Не туда.
Это даже не асинхронный метод, ты просто гадишь в тредпул. И да, в конструкторах так делать не надо, потому что пользователь не ожидаем там такой хуйни. Чисто технически все будет норм работать, но тебе нассут на ебало.
Это одноразовая акция, делается только на старте приложения и пока конструктор у этого класса не отработает ни один другой сервис не сможет построиться.
Мне лень просто прописывать в классе какой-либо инициализатор, а потом заставлять все хостед сервисы сидеть и ждать когда он пробздиться. А так за меня все DI сделает.
Да. Один раз сделаешь и не отмоешься
То же говно с Newtonsoft.Json
В JsonSerializerSettings есть свойство культуры, но сериализатору и десериализатору ПОХУЮ.
>var settings = new JsonSerializerSettings() { Culture = CultureInfo.CurrentCulture };
>var myArray = new double[] { 10.4, 17.9, 100.7 };
>string jsonString = JsonConvert.SerializeObject(myArray, settings);
>Debug.WriteLine(jsonString);
результат:
>[10.4,17.9,100.7]
И еще непонятно в чем отличие
CultureInfo.CurrentUICulture от CultureInfo.CurrentCulture
Если думаете, что первое как-то влияет на отображение данных в GUI, то хуй там плавал.
и правильно что пох. ради тебя он не будет создавать невалидный жсон
хочешь как надо - напиши свой конвертер
>>75320
Пришел к такому варианту. Если установить культуру для текущего треда, то можно отдельно для интерфейса установить текущую культура, а для всего остального инвариантную.
>Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentCulture;
>Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
Тогда в лог будет записываться с инвариантной, ну и парситься нормально.
Еще бы сделать так, чтобы это вручную не писать в каждом проекте, чтобы это было по умолчанию.
>>75441
Да всем похуй на культуру, конечно. Логеру похуй, десериализатору похуй, а пользователю надо показывать данные в текущей культуре. Какие-то плагины вовсе отказываются работать, если у операционной системы не EN-культура.
>Thread.CurrentThread.CurrentUICulture = CultureInfo.CurrentCulture;
Не работает... Это говно не работает.
Работает пикрил.
Кто нибудь знает стандарт как надо делать правильно?
>>75459
>>75466
Короче прочитал я про CurrentUICulture, которая якобы должна влиять на пользовательский интерфейс, но по факту в WPF никак не влияет. И еще непонятно почему одни меняют так
>Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
а другие так:
>CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
Ты поехал что ли? Представление чисел в джейсоне не зависит от культуры, оно всегда одинаковое.
Я им не особо пользовался.
Есть сервис(всмысле демон, винсервис), написанный на .NET. Он там своей работой занимается, выполняет ее. Примерная архитектура - прикриплейд.
В общем. Все было заебись.
Возникла охуительная идея - приделать к нему веб-морду.
И вот тут уже стало не забись.
Собственно, в чем проблема. Проблема в том, что сервис писался без всех этих ДИ и прочего. Там своя логика инициализации, самописный DI, свои логи. В общем, все самописное.
И теперь надо это как-то с ASP.Net сдружить.
И я реально не знаю как сделать правильно. Типа можно хуйнуть наружу какую-нибудь статику и через нее общаться. Но это выглядит как залупа жи с точки зрения АРХИТЕКТУРЫ.
Я тоже думал об этом.
Но хотелось бы, чтобы оно было все в одной сборке и одним процессом, и постепенно как раз таким хреном отказаться от клиента.
Адаптер может быть встроен и в сборку.
Для примера цикл от 0 до 10
>for (int i = 0; i < 11; i++) {}
Обратный цикл от 10 до 0
>for (int i = 10; i >= 0; i--) {}
Нужен гибрид этих двух циклов
Если флаг IsReversed = false, то цикл движется от 0 до 10
Если флаг IsReversed = true, то цикл движется от 10 до 0
Что-то более элегантное чем это:
>int start = 0, end = 11;
>if(IsReversed) (start, end) = (end, start);
>int incr = IsReversed ? -1 : 1;
>for (int j = start; j != end; j+=incr) {}
Например условие 'j != end' можно перескочить и цикл станет бесконечным.
Написать иф с двумя циклами. Либо через Linq.
Я БЫ СДЕЛАЛ ТАК!
Почему код с первой картинки - работает медленнее и начинает кидать исключения если выполняется часто, а после - делает приложение недоступным в течении минут 10-20.
А второй, ебанутый код - работает отлично и никаких исключений не кидает и при этом эти нагрузку выдерживает.
Контекст - pgSQL,
Мне как-бы понятно, что дело в том, что насоздавались подключения, все такое. Но почему даже после того как все исключения обработались - минут 5 ни один новый запрос к базе не удается выполнить-то в первом примере кода? И как быть в таком случае?
Второй код - работает, но его проблемы очевидны, например, если какой-то люто долгий запрос к базе будет, все должны будут ждать, плюс, сам по себе - костыль и страшно смотрится.
Да, я знаю, что могу увеличить число подключений к БД, поднастроить как к базе подключаться и настройки все эти, проблема в том, что второй код - работает и работает просто неприлично хорошо.
Поясните, я просто хочу на своём ПК эмулировать андройд устройство и управлять и в C# как в селениуме.
Что мне устанавливать то нахой?
Вот у меня была библиотечка простая, чтобы с TCP работать. Был класс TCPServer (https://github.com/BakaVaka/NetLib/blob/master/src/BakaVaka.TcpServerLib/TcpServer.cs)
И меня все устраивало. Сверху я там нахуевертил уже прикладной слой, все заебись, работало, никто в хуй не дул.
Внезапно, нужно оказалось поддержать UDP, и так, чтобы все что сверху нахуевертил - не сломалось.
И единственное удобное решение для меня оказалось - переписать класс TCPServer в некий NetServer который будет и UDP и TCP принимать. А для прикладного уровня все так и остается, только на уровне конфигурирования - заменить класс TCPServer на NetServer
Но ведь это прямо против того что озвучивает OCP. Но если бы я пытался наследоваться там, и делать какой-то UdpAndTcpServer : TcpServer - это же было бы просто пиздец какой говной.
А задачи изначально и не стояло, что будет какой-то там UDP. Задача стояла: вот тебе 2 дня, по TCP прими пакетик, распарсь, обработай и отдай ответ правильный.
В общем. Я прошу пояснить, как я должен был проектировать, не зная о том, что будет через год, чтобы не обосраться с буковкой O.
Сто лет уже не работал с EF, но я подозреваю, что у тебя подключения не разрываются после использования, а так и висят, пока таймаут не наступит.
Вероятно в настройке DI надо более ручками прописать цикл жизни dbContext. Хотя, как я уже говорил, ничего уже не помню.
Забей хуй
Если про те что к БД - оно понятно что не разрываются. Как-бы суть в том, что они в обоих случаях не разрываются.
Непонятно какого хрена они не переиспользуются, даже после того как контексты задиспозились. И это какая-то специфичная проблема Postgres, потому что раньше с MSSql работал и там вообще ниче делать не надо было, все само как-то разруливалось.
Ну и да. Можно настроить автоматическое закрытие после диспоза, но это ПИИИИИИЗДЕЦ как убивает производительность. Не. ПИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИИЗДЕЦ как. Плоюс, полностью проблему не решает при высокой нагрузке, просто меньше время недоступности базы будет.
Попробуй на монгу перейти.
Ситуация такая: при запуске проги она должна создавать новую SQLite БД с таблицами, если уже существующей не найдено. Сам код для SQLite находится на уровне Model. Чтобы реализовывать такой функционал, приходится дергать код из model в пределах App.axaml.cs.
Насколько сильно такой подход противоречит сути MVVM?
Авалония не может в корректную работу с СУБД. Переходи на Ето.формс. Там всё прекрасно с МВВМ.
И как там сделать такой функционал не ломая MVVM?
> при запуске проги она должна создавать новую SQLite БД с таблицами
Так и дергай при запуске проги, лул.
Обычный подход это что-то в духе прикриплейд. Прям в мейне, инициализируешь, радуешься.
> Чтобы реализовывать такой функционал, приходится дергать код из model в пределах App.axaml.cs.
> Насколько сильно такой подход противоречит сути MVVM?
Приложуха по своей природе является точкой входа, она в любом случае видит всех. Не понимаю, в чем у тебя проблема? Ну дёргаешь ты модель из точки входа. И чо? Как это нарушает остальную работу объектов? Они-то друг друга уже не видят, после того как точка входа отработала.
>Авалония не может в корректную работу с СУБД. Переходи на Ето.формс. Там всё прекрасно с МВВМ.
Лопата плохо варит кофе - в этом выражении столько же смысла, сколько и в твоем.
Охуенная тема, братан
Я за фот эти фронтенд штуки ваще не шарю.
Как делают приложения такова типа? ну что бы без перехода по страницам, в одном окне кнопочки, менюшки, всплывающие окошки.
React + что то на бекенде?
В самом этом защекоине просто отсылаются post запросы в эвентах
Хочу такое же сделать.
Что учить?
Ну простую страничку я то сделал SignalR со счётчиком, кляцаешь и +1. А как вот эти выебоны с менюшками то делать?
Блять ненавижу фронт но что делать то(
На парсерах, регерах далеко не уедешь(
Или вот пример.
Я говорю в том что приложение максимально быстро работает.
Жмём кнопку мгновенно переходит по кнопке, адрес меняется, но контент сменяется очень быстро, так же как и при нажатии кнопки назад.
Метанит например грузит всю пагу долго в сравнении.
Корочи как такое делать то?
Ты крайне криво выражаешь что ты хочешь.
Ну да ладно.
Если про обычный подход к SPA, то делают вот так:
У тебя веб-сервер(похуй что, хоть nginx, хоть .NET'овский какой, хоть, аппач). Его цель - отдать статичный контент
Точкой входа является index.html
В этом index.html что-то в духе:
<body>
<div id="app">loading...</div>
<script src="/js/app.js"/>
</body>
Т.е. один html документ, остальная логика по работе с фронтендом лежит в app.js, который может быть хоть ванильным JS, хоть фреймворком каким-то. Этот app.js после загрузки - подсунет в #app - содержимое приложения, все эти менюшки, карточки и прочее. Ну, собственно, будет с домом работать, делать всплывающие менюшки, плюс - наебывать браузер играясь с путем, чтобы можно было ссылки шарить и вело себя +- как классическое статичное веб-приложение.
Бек, при этом - обычно ничего про представление не знает, он работает только с апишками, принимает запросы - отдает json'ы, может быть сверху чет с веб-сокетами.
Собственно. Так и делается.
Простейший путь для .NET'чика - взять ангуляр + .NET и сделать по гайду.
>Ты крайне криво выражаешь что ты хочешь.
Ну да я не шарю вот за эти штуки
До недавнего времени я генерил тоннами html страницы и засирал ими просторы интернета, но видимо пришло время изучать фронтенд ебучий
Где вы исполняете код во время разработки? Я имею ввиду, нужно проверить работоспособность какого-то участка кода и при этом не срать в Program.cs.
Можно сделать как-то чтобы на него ссылка в решении не добавлялась?
>Простейший путь для .NET'чика - взять ангуляр + .NET и сделать по гайду.
Еще как вариант - блазор
>Я имею ввиду, нужно проверить работоспособность какого-то участка кода и при этом не срать в Program.cs.
Приведи пример
ТЕСТЫ, МАТЬ ТВОЮ, ДЛЯ КОГО ПРИДУМАЛИ?
Я вот срсли не понимаю, какого хуя все так тесты не хотят писать. Ты его написал. Зафиксировал поведение. Кайф. Если начнешь рефакторить и чет наебнешь - хуяк, тесты красные, пиздец, сразу идешь и чинишь.
Опять же - у тебя под боком все лежит, кайфуй, пользуйся.
При этом - тесты ты можешь встроить в CI. Какой-то хуйлан прислал ПР на 500к строк, тесты упали, ты даже не смотря эту хуйню шлешь хуйлана переделывать.
Короче. Единственно верный ответ - нормальный проект с тестами. Бери. Пользуйся.
А прототип своей фичи сразу делаешь там где он должен будет быть, и проверяешь его как раз своими тестами. Можешь тесты писать до написания фичи, можешь после.
Нихуя, спасибо)
>Я вот срсли не понимаю, какого хуя все так тесты не хотят писать.
Потому, что на написание нормальных тестов тоже нужно время, а его обычно никто не выделяет (как и на написание документации)
>Ну вот мне надо прототип фичи какой-то реализовать используя уже написанные классы и ресурсы остального проекта, или проверить как дотнет себя в той или иной ситуации ведёт.
Так а в чем проблема? Создаешь отдельный класс(ы) в отдельном файле(ах), фигачишь туда нужную тебе логику и используешь. Потом удаляешь когда надоест.
1. Ты в любом случае отлаживаешь. Вот часть этого времени - можешь на тесты переложить. В долгосрочной перспективе - это окупится в любом случае.
2. Чел все равно хочет тестировать, но сейчас для тестов пользуется костылями, так пусть пользуется инструментами, которые лучше для этого подходят.
Опять же, мой личный опыт показывает, что если нормально аргументировать, руководство таки согласно выделять время на тесты, но почему-то уже разработчики - не хотят их писать.
ну вот удаляешь ты элемент текущий (а то и вообще список чистишь) и selected автоматически меняется, а ты бац и отменяешь....и где теперь твой бог?
Бог сделает так, чтобы в итоге не было выбрано ни одного элемента.
Проблема в том, что данные в метод не отправляются. Описал свою проблему на stackoverflow, там скинули код, который у них работает, но у меня все также – метод не принимает никаких значений. Вообщем хз че делать, есть подозрения что с библиотеками что-то не так(хотя для тестирования скрипта, предоставленного в SO, подключал уже ссылку на ajax). Может кто-то знает, как это решить, буду благодарен)
Прототипы очень удобно писать в linqpad. Единственный минус — надо премиум версию, чтобы работал автокомплит и нугет.
upd: решил проблему
А как вы, в ваших асп.нетах используете компоненты?
просто создаете свой view component и прокидываете ему параметры из контроллера среди прочих данных?
Это просто View называется.
В контроллерах есть специальный метод View() с кучей перегрузок, в большинстве он принимает объект, который называется модель. Соответственно в методе-обработчике запроса в конце ты просто пишешь View(myOxuennbI
С другой стороны, в соответствующем шаблоне *.cshtml вверху пишется @Model <тип модели>, чтобы движок мог давать подсказки и помечать ошибки.
Дополнительно к этому есть словарь (хэшмэп, но не настоящий, не бросает исключения если ключ не найден, например) ViewData и динамический объект ViewBag (второй появился позже и, видимо, для выпендрёжа), их тоже можно заполнить в контроллере, а потом использовать в представлении.
нет. я именно про View components, которые этакие виджеты/контролы в асп.нет, чуть мощнее partial view
В пхп есть замечательный фреймворк Nette, который отходит от принципов навязанных MVC и вводит компонентную модель - то есть ты заводишь компоненты, в контроллерах их достаешь, изменяешь их состояние, а потом в виде компонент с текущим состоянием сам себя рисует.
Более того, компоненты там вклиниваются в процесс запроса, то есть компонент сам может доставать и прокидывать через запрос нужные ему persistent параметры
Также есть сигналы - сделать запрос компоненту только, а не всему пайплайну контроллеров
Также может рисовать себя частично
В асп.нет же, как я вижу, View components - просто partial views со своим code-behind и все. В запросе не учавствует, параметры ему в контроллере собирай (и сам их считай) и дотаскивай вместе со всеми. Ну примитив какой то.
Ну ладно пользуясь тем, что там DI и скоуп рождается на запрос...можно навернуть костыль чтобы к компоненту можно было обратиться из контроллера и изменить его состояние, а он себя отрисует.
Но все равно как то уныло.
Может конечно. Слишком много денег и времени на это нужно чтоб его с ссаной явы переписать
да как хочешь
никто не ограничивает никак.
можешь какую угодно иерархию - раз
можешь оборачивать модели - два
а можешь не оборачивать, а копировать во вьюмодели данные, а потом обратно - три
но не можешь разгадать гребанную новую капчу с двача - ноль
Собственно. Ситуация.
Есть сущность, к которой надо биндить объект. Условно, сессия.
Объект, который биндится, после диспоза - должен освободить эту условную сессию.
НО, в системе может возникнуть другой объект, к которому надо прибиндить эту сессию. Тогда я насильно диспозю первый объект и перебиндиваю.
Проблема. Если в это время шла работа какая-то через эту сессию с тем объектом, все может внезапно накрыться пиздой.
Как хотелось бы? Хотелось бы, чтобы если перебиндили - как-то подменялся объект на новый. Но как это сделать по человечески - я не могу придумать.
Ознакомься с референсными объектами, на основе подсчёта ссылок.
https://learn.microsoft.com/en-us/windows/win32/com/managing-object-lifetimes-through-reference-counting
Ты хочешь диспозить объект в рэндомный момент.
Не делай этого. Чудес не бывает. Меняй подход
Например, у жетбраинс с их лайфтаймах эту проблему решают возможностью запретить терминацию лайфтайма на время какой то операции.
С просто диспосабле тебе нужно токен занятости и при вызове диспоз просто планировать его. Когда его все отпустят токе тогда и делать запланированный диспоз
>>83700
Окей. Надо наверное немного контекста.
Сессия - не просто так.
Есть клиенты на хреновом канале связи, который периодически может отваливаться. На моей стороне - я не могу задетектить отвал мгновенно(потому что закрывается он с большой задержкой, которая не от меня зависит). Но клиенты - долбят часто и таким образом - сами переподключаются.
Собственно, с этими клиентами хочет связываться уже другое ПО. И для него - все должно быть как-бы прозрачно, будто НЕ ЕДИНОГО РАЗРЫВА.
И вот для этого - придумал вот такой класс как "сессия", которая держит текущее подключение. Если клиент переподключится - я хочу просто заменить соединение на актуальное чтобы со стороны выглядело, будто разрыва не было, просто была задержка. Задержки - ок.
Ну например что бы он что то проверял в цикле и если шо отправлял запррос на сервер.
Хз. У меня вполне бодро работает. Профилировщик в студии только сразу на 20% срезает производительность.
Я проверял на 8.0, там точно такая же ситуация, как приду домой могу скриншот кинуть.
Сделал я Blazor WebAssembly приложение.
Просто для теста. Так же в приложение добавил телеграм бота который просто в ответ на сообщение отвечает ссылку на моё приложение.
Дак вот как я думал оно будет работать:
Само приложение будет крутится в запущённом виде на сервере. Ну собственно как оно крутится в дебаге.
Сама страничка приложения будет обрабатывается на клиенте и не трогать сервер. Пользователь будет жать на кнопки и будет рад.
А на сервере будет крутится Bot.StartAsync(); для работы бота.
Но оно мне скомпилила все в ВАСМ и теперь бот хостится на клиенте. То есть если кто то зашёл в приложение то бот начинает работать.
А мне надо что бы бот работал на сервере а пользователь работал только с ВАСМ приложением, приложения изредка отправляет запросы на сервер для синхронизации. И то когда я в кода приложения определю когда отправлять запрос.
Это мне получается Блейзер Гибрид нужен? Точно не Сервер так как мне не надо держать всегда подключение открытым через СигналР.
Блин. Второй тест - проебался с выводом, но там через рекурсию.
Блин, чем ты занят?
Одно дело повторить дебильный код, который тестирует производительность вызова методов.
Совсем другое просто так писать ещё один дебильный код который тестирует непонятно что.
Бинарное дерево хранится в виде массива значений. Время генерации — время создания массива. Наносекунды.
Hybrid — это про то, что у тебя до того, как скачался wasm, оно работает в режиме Server, а потом в режимe Client.
К твоей задаче это никакого отношения не имеет.
Hybrid это для запуска вне браузера, то о чём идёт речь это дефолтное приложение с режимом рендеринга Auto.
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0
Это то что ему как раз надо, можно всё приложение сделать как WASM компонент и оно будет крутится в браузере автономно.
Ну. Смотри. На мои вопросы не отвечают. На работе - главный затрахал. Коллеги - постоянно ругают мой код, дескать он непонятный.
Че мне делать остается, кроме как в пятницу вечером фигней страдать на бордах?
А тестирует тот код мою память по вузовской программе, :p.
Если ты про то чтобы апи крутилось на сервере, а фронтенд в WASM то тут всё так и будет, создай дефолтный проект Blazor и заметишь что у тебя в решении два проекта, один из них это Client.
Спасибо и сразу спрошу)
Какая логика у таких приложений?
Вот мне нужно при запуске приложения / запросить данные с сервера.
В WASM я бы запросил из через апи обратившись к контролеру.
А как тут это сделать?
Создать компонент в серверной части с нужным мне кодом? Ну там с обращением в бд и всё такое и встроить его в приложение?
Твой первый проект это серверное приложение, тот что с .Client это ассембли которое собирается в WASM и запускается в браузере в зависимости от рендермода компонентов(смотри документацию).
Если для тебя допускается подождать пока загрузится и закэшируется рантайм дотнета в браузере то можешь сделать что-то типо такого в App.razor(пик1). Это явно разделит твой клиентский и серверный код на два рантайма, в ином случае смотри документацию по Interactive Auto рендермоду.
Данные передаешь по HttpClient.PostAsJsonAsync в апишные контроллеры или по SignalR.
Могу тебе посоветовать годный канал по этой теме, в ютубе "IAmTimCorey Blazor Auto"
>Данные передаешь по HttpClient.PostAsJsonAsync в апишные контроллеры или по SignalR
Тогда зачем это всё? В чём разница этого приложения и простого WASM блейзор +webapi приложения?
Мне по сути нужно изредка отправлять запросы. Большая часть данных на странице рендерится у клиента и только некоторые данные на ней получаются с сервера.
При использовании SignalR вообще весь смысл теряется, так как WASM нужен был для экономии ресурсов сервера и что бы не держать подключения открытыми.
>Тогда зачем это всё? В чём разница этого приложения и простого WASM блейзор +webapi приложения?
Смысл в разных рендермодах, в частности Auto который делает для клиента бесшовное переключение с серверного рендера на WASM когда рантайм передан. Ну а ещё удобно то что по дефолту в одном решении. Универсального транспорта, который бы абстрагировался от текущего рантайма, пока что не завезли.
>в частности Auto который делает для клиента бесшовное переключение с серверного рендера на WASM когда рантайм передан
Это в каком смысле?
Типо клиент первый раз зашёл на сайт и пока ему передается WASM сайт работает с сервера а когда передался то переключается на WASM ? Ну дак это же только 1 раз то будет.
Я думал будет как то так: Заходит клиент на сайт грузит всё приложение с логикой. Потом к примеру находит на /game там WASM приложение делает запрос к апи получает инфу и строит страницу.
То есть при посещении страницы WASM клиент получает инфу и уже на ней строит страницу.
Только что будет когда я поменяю логику в WASM ? Её перезагрузит сразу?
> Одно дело повторить дебильный код, который тестирует производительность вызова методов.
Почему на одном языке дебильный код, тестирующий производительность вызова методов, выполняется в 10 раз дольше, чем на другом — нормальном — языке?
Приложение на хостинге.
Запрашиваю своё ип со сторонего сайта.
@rendermode RenderMode.InteractiveWebAssembly -- получаю свой ПИ адрес
@rendermode RenderMode.InteractiveServer -- получаю ИП адрес сервера.
@rendermode RenderMode.InteractiveAuto -- получаю ИП адрес сервера. И вот тут как то не логично. Правильно ли я понял если связь сервером нарушится то я получу ип адрес клиента? Или как это работает?
Далее вот еще у меня есть эндпоинт
app.MapGet("/time", () => DateTime.Now.ToShortTimeString());
Я делаю запрос на него.
@rendermode RenderMode.InteractiveWebAssembly - в браузере виден запрос на https://localhost:7039/time всё ок.
@rendermode RenderMode.InteractiveServer - Вылетает эксепшен.System.NullReferenceException: "Object reference not set to an instance of an object." Я так понял что он не знает по какому адресу обращатmся. Но как по мне тоже не логично, он ведь должен знать что есть локальный эндпоинт /time
Также вот еще
builder.Services.AddScoped(sp =>
new HttpClient
{
BaseAddress = new Uri("https://localhost:7039/")
});
Тут для разработки локалхост. А можно как то установить текущий адрес моего сайта? ну к примеру сайт на домене zalypa.com и что бы атвоматом ставило? Мне и ручками не в падлу прописать но всё же
Отчего это зависит то?
>>87779
При рендере страницы проверяется наличие рантайма, если тот есть то компонент рендерится в режиме WASM. Новые компоненты проверяют, в каком режиме работают уже существующие компоненты на странице и по ним выбирают себе рендермод. Для того чтобы гарантированно переключился рендермод страницу следует полностью перезагрузить.
По дефолту включен пререндер. С ним у тебя при рендере компонента он сначала рендерится на сервере.
https://learn.microsoft.com/en-us/aspnet/core/blazor/components/prerender?view=aspnetcore-8.0
@rendermode @(new InteractiveAutoRenderMode(prerender: false))
Чтобы выключить.
Инжекти NavigationManager для того чтобы работать с адресами.
https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-8.0
Но по итогу, в обозревателе они остались слипшиеся (Test3), но в логе имена прекрасно отображаются.
Как сделать, чтобы тесткейсы разделялись в обозрвевателе тестов? (как на пике 1)
https://pastebin.com/Tm1iyiL2
Не прошу решения. Но прошу направить мысль.
Допустим. У меня есть 100к подключений. Долгоживущих, все дела.
Я хочу подключиться к 10к из них и "пообщаться".
Наивная реализация дает крайне хуевую производительность.
Т.е. как я сделал:
Тот кто хочет общаться - говорит, мне кому отправить сообщение. Я беру, проверяю в словаре, если есть такой - передаю ему, если прилетит ответ - отправляю первому. И так в цикле.
И на большом кол-ве это чет хеувастенько работает.
Я правда не пойму что хуевастенько работает. Типа если верить профилировщику, 89% времени работы приложения выполняется некий GetNext() и какие-то вуду-штуки с AsyncMethodBuilder'ами.
Объясню сразу в чем хуевастенькость.
Такое ощущение, что часть из вот тех общателей 10к вообще не обрабатываются.
Я вижу какую картину. Вот 100к подключений я с помощью докера и прочих изъебств намутил к своему серверу. Они стам сидят-пердят, ниче полезного не делают.
Вот, я беру, хуячу 10к других челов. Выбираю рандомно из 100к 10к тех с кем общаться и кто не занят.
Ок.
И где-то процнтов 30 +- нормально начинают обмениваться пакетами. А остальные - висят и будто до них вообще не доходит очередь.Ну. Т.е. они подключились, ок-да. Отправили пакет. Даже первый ответ получили. Отправили следующий и ждут. Ждут. Ждут.
Думаю о том, что надо имплементировать свой эвент-луп и свой тредпул, и обходить самому тех кто подключился.
В общем. Я нубан.
Работаю шарпером на заводе.
Вот, недавно подпустили к проекту, на котором матерые C++'еры работали, но на шарпе.
Увидел там нечто похожее на прикриплейд.
Можете объяснить, нахуя и зачем так делать?
> C++ тред похоже мертв. Спрошу тут.
Ты конечно молодец, спросил в предыдущем плюсотреде, из которого все перекатились в новый ещё два месяца назад.
Та как узнать-то?
Вот на доброчане, царствие ему небесное, ссылку всегда оставляли на новый тред.
ОП хуй неправильно перекатил, не вставил тему в название треда
>Можете объяснить, нахуя и зачем так делать?
1 вариант - там что-то критичное, что без этого не работает никак или работает в разы хуже. Возможно дергают какую-то нативную библиотеку, которая очень древняя и никто уже не может/хочет её переписать и т.д. В моей практике такое было при работе с ЭЦП и криптопровайдерами, там без вариантов.
2 вариант - ретроградные байтоебы, привыкшие на всем экономить и считающие, что позволять компилятору и CLR самой заниматься менеджментом памяти - не тру.
Что я имею ввиду.
Вот у меня есть библоитека myLib.dll. Она использует Newtonsoft.Json. Я хочу чтобы Newtonsoft.Json.dll была включена ВНУТРЬ библиотеки myLib.dll, в идеале, чтобы при использовании моей библиотеки - никто даже не знал про этот Newtonsoft.Json.dll
Можно ли такое намутить?
Наверное криво объяснил.
Короче. После билда библиотеки - я получаю 2 файлика в выходной папке: myLib.dll и Newtonsoft.Json.dll. Я хочу чтобы на выходе - был один файлик. myLib.dll
Им удобно пользоваться и он выдает более предсказуемый результат и реже надо свои обработчики писать.
git
Клонируешь себе исходники ньютонсфта и вкорячиваешь их в проект с myLib с правкой неймспейсов.
Вопрос только нахуя так делать (скрывать наличие библиотеки) ?
> Вопрос только нахуя так делать
Ну. Я вот начитался гайдов. И решил сделать себе ПЛАГИННУЮ АРХИТЕКТУРУ с горячей перезагрузкой.
Собственно. И мне не нравится, что если у плагина - зависимости, то надо их руками подгружать руками постоянно. Я хотел бы, чтобы плагин был максимально самостоятельным. Одна dll положенная в нужную папочку и все. А сейчас - приходится при "установке" плагина - еще и разруливать все его зависимости, либо складывать их к основному приложению, что сам подход с: просто закинть одну dll в нужную папочку - делает ебаным и тогда уже можно забить на эти плагины и делать как обычно.
В случае если плагин без зависимостей - там на самом деле круто выходит. Чет дописал в плагине, собрал только плагин, оно перезагрузило плагин и все ок работает без необходимости останавливать и пересобирать все это дело. Но вот если пара зависимостей - уже ебано.
1. Ты похоже пытаешься сделать слишком комплексные плагины.
2. Если ты изначально подразумеваешь, что тебе нужен будет функционал ньютонсофта, то подключи его в основной проект и не парься.
3. В большинстве продакшена от ньютонсофта стараются отказываться в пользу System.Text. Да он может быть не так удобен, в нем может не быть некоторых фишек из ньютона, но он потихоньку становится новым стандартом и через несколько лет ты ньютон мало где уже встретишь.
> Ты похоже пытаешься сделать слишком комплексные плагины
Ну. Да. А так нельзя делать разве?
У меня как-бы основное приложение это демон. Сидит в системе и не особо заметно, работает в фоне.
А все остальное - я хотел делать через плагины.
Пару плагинов тестовых - таки написал, но они как раз были маленькие, чтобы просто проверить как это работает. Сбор статистики работы там, вот это вот.
Собирался сделать плагин для "визуализации", который бы позволял при желании - еще окошко рисовать и в трее иконку и какое-то управление. Плюс - плагин, для работы со всем этим делом через веб-апи, чтобы опять же, при желании - можно было через браузер поуправлять демоном и посмотреть че там происходит.
И я даже сделал первый крупный. Но мне не нравится, что приходится руками зависимости все эти рулить. Плюс, я в этом деле новичок и боюсь, что вдруг там какие-то конфликты будут, чи шо. Вот как .NET будет вести себя. если я загружу две Assembly разных версий? Он это поймет или нет?
на завод уходи
какая тебе жава. там IDEA которую делает жетбраинсы, которые русских послали.
так что на завод. будешь там дворником
сторожем
во-первых, а как ты тестируешь 100к подключений? как ты подключаешь?
во-вторых, 100к на докере - не дохуя ли? Не так давно была проблема 10к на целых серверах, а ты уже 100к на каком-то докере
в-третьих, эти 100к не сидят-пердят, ядро вообще-то ебенит не в себя, обрабатывая пакеты
в-четвертых, возможно у ядра есть ограничения на создание соединений
в-пятых, очень мало данных: может у тебя цп не успевает, может памяти не хватает и в своп уходит?
Понадобилась помощь антонов двач выручай.
Я сам по себе далёк от программирования, тем более на сишарп, но по работе потребовалось выполнить передачу данных на прибор по UDP-протоколу. Китайские друзья предоставили код на сишарпе для выполнения этого действия, но я совершенно не понимаю, как мне запускать этот код и как им пользоваться.
Реквестирую подробный гайд как создать проект, добавить туда файл с этим кодом и запустить его используя Visual Studio Code.
Ютуб завален видосиками по созданию проектов на шарпе в vscode, посмотри любой из них и дописывай в Program.cs что угодно.
>Плюс - плагин, для работы со всем этим делом через веб-апи, чтобы опять же, при желании - можно было через браузер поуправлять демоном и посмотреть че там происходит.
Я х.з. как с этим сейчас, но в Core3.1 точно были проблемы с созданием новых API из подгружаемых сборок.
>Собирался сделать плагин для "визуализации", который бы позволял при желании - еще окошко рисовать и в трее иконку и какое-то управление.
Я не десктопщик, но вот есть у меня подозрение, что с этим ты прям соснешь-соснешь. Как минимум будет ебля с контекстом синхронизации и UI-потоком. Под это дело проще какой-то дополнительный клиент запускать, чем плагинами мутить.
Ты лучше бойся, что все это заблочат с этой стороны ебанутые РКН-щики. Это как раз более вероятно.
Ребята, у меня вопрос.
Не смейтесь, я литерали даун, нужна помощь в элементарной математической программе. Надо чтобы в консоль бесконечно и последовательно печатались числа фиббоначи. Сижу уже час, мой код не делает то что нужно и я где-то на подсознательном уровне понимаю что мой код и не должен работать, но я слишком тупой чтобы написать правильный. Что я должен в нём изменить чтобы всё работало?
Везде предлагают использовать библиотеку Widows.Forms, но как ее юзать, если у меня .NET, который Core?
Во первых винформс тыщу лет работает на core
Во вторых ты где то не там гуглишь. Решению для wpf миллион лет и оно переехало на core
Убери, чё как чушпан? Убирай, давай!
Это был хороший цикл, может быть даже лучший, который у меня был.
Охуенный код в стиле "наеби соседа", от себя я бы добавил, чисто для удобства дебага перед сборкой бинарника и отправкой соседу, пикрелейтед:
... но если всё таки, вдруг, код нужен не соседу, а преподу в вузеке, то надо добавить что-то типа этого:
Жпт чат говорит что бы мне взаимодействовать с ЖС библиотекой её нужно загрузить.
Мне нужно взаимодействовать с библиотекой
https://telegram.org/js/telegram-web-app.js
Её вроде как нельзя грузить себе, она должна загружаться с ТГ сервера.
Например хочу выполнить функцию close() что бы закрыть мини апку. В самом ЖС я бы сделал вроде как вот так window.Telegram.WebApp.close() и моё приложение закрылось бы, а как мне это всё скрестить с Блазером?
Помогите плиз с 1 примером.
Так у тебя в переменных обычный int будет и ты очень быстро получишь переполнение.
> и ты очень быстро получишь переполнение
Учитывая, что каждое следующее число после чтения инпута, то не очень быстро. Даже если положить книжку на клавиатуру.
...Но это не важно, ведь в условии задачи, сформулированной аноном, не говорится ничего о том, что в решении задачи нужно что-то предпринимать против переполнения.
> не очень быстро. Даже если положить книжку на клавиатуру.
Ладно, я проверил и я спиздел. Всё равно быстро.
В какой-то момент перестает видеть связь между xaml и кодбихайндом. Подсвечивает ошибку InitializeComponent и любые попытки обратиться к компоненту xaml по имени.
Пытался чистить .vc, не помогало. Только после чистки obj сработало.
> Как бороться с этой штукой
> Только после чистки obj сработало.
Сам же ответил. Чистить обдж, чистить вилкой. Для удобства можешь через dotnet clear
> Встроенного решения не нашел. Предлагают сторонние библиотеки, но я не хочу ради этой мелочи добавлять.
Вот же пишут по первой же ссылке из гугла
>NotifyIcon is not implemented in WPF as it is in Forms, but you can still use the Windows Form NotifyIcon, it resides in the System.Windows.Forms namspace.
Ты можешь использовать иконку из формсов в ВПФ-приложении. И это не стороннее решение. Всё встроено в дотнет искаропки.
>Always has been
@
>NotifyIcon is not implemented in WPF
>Ты можешь использовать иконку из формсов в ВПФ-приложении.
Не могу, я прикрепил скриншот. У меня NET8, а библиотека Windows.Forms на Framework.
> а библиотека Windows.Forms на Framework.
Значит у тебя что-то недоустановлено.
Попробуй в отдельной папке создать новое приложение винформс, увидишь, оно у тебя создастся как нет8.
Вот пожалуйста, всё создаётся и запускается на восьмёрке.
Да, вижу. Но как объединять платформы?
Через добавление референсов доступна библиотека только на Framework, а она не совместима.
Платформы объединять я не знаю как.
Щас погодь, я попробую воспроизвести у себя. Если я правильно понял, мне нужно:
1. Создать ВПФ приложение.
2. Попытаться подключить класс NotifyIcon из формсов.
3. Выскочит ошибка и ничего не получится.
Всё верно?
>>92594
Нашел как
https://stackoverflow.com/questions/72058558/how-can-i-add-system-windows-forms-to-wpf-application-when-adding-via-reference
- Removed reference/dependancy entirely
- Right-click project, Unload
- Right-click project, Edit project file
- Add the following:
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
- Reload project file
- Add "using system.windows.forms" to the top.
Да, я нашел как >>92619
Короче надо выгрузить проект, добавить в свойства проекта
> <UseWindowsForms>true</UseWindowsForms>
Потом снова загрузить проект, и тогда будет доступна библиотека
> using System.Windows.Forms;
Единственное, что выскочит неоднозначность некоторых элементов, типа Application. Пришлось писать так
> public partial class App : System.Windows.Application{}
Библиотека System.Windows.Forms загружается по умолчанию во все документы.
Лол, я литералли сделал то же самое и уже собирался показывать результаты. Единственный нюанс. Блять, и это уже опередили.
А есть вариант как глобал юзинги отредактировать? Я знаю про отключение полностью, но мне кажется, что тут надо просто исключить строку с винформсами.
Чтобы не ебаться с неоднозначностью сделай солюшен из двух проектов, один - либа нет8(!) на винформсах, в которой всё подключено и реализован твой трей, а второй проект - твоя приложуха на ВПФ, в csproj запихиваешь ссылку на либу и всё будет собираться одним заходом.
2 взять готовую либу типа
https://github.com/hardcodet/wpf-notifyicon
или эту не пробовал
https://github.com/nullsoftware/TrayIcon
а не заниматься херней
Да не хочу я для такой мелочи либу качать. Мне не нужны какие-то сложные нотификации со вплывающими сообщениями или динамическими иконками.
Двачую.
> а не заниматься херней
Это не херня.
Анон вручную напишет реализацию простой иконки и разберётся, как это работает. И прокачает скилл.
зачем? вот я не знаю и не вижу смысла знать как она делается в этих формсах, когда формсы давно забыты мной и нахрен не нужны.
> формсы давно забыты мной
Но они не забыты майками и регулярно обновляются, допиливаются, обогащаются фичами. Почему-то у майков они не легаси и не депрекатед. Например, туда завезли МВВМ. Так что, это всё твоё субъективное мнение.
> и нахрен не нужны
Тебе. Не забывай добавлять это слово, манипулятор мамкин. Они не нужны тебе. Говори за себя, а не за всех.
так они и винапи допиливают. пиши на голом винами, чего уж там.
тот, кто озаботился вопросом иконки в трее пишет на WPF, так что ему от поддержковости винформсов ни холодно ни жарко.
да они многим не нужны. зачем писать на том, что тебя ограничивает. MVVM целый ух ты ж. А в остальном все так же переопределять OnPaint?
> пиши на голом винами, чего уж там
И напишу.
И ты никак мне не помешаешь.
> А в остальном все так же переопределять OnPaint?
Может быть и переопределять. Я мокрописечки не писал, мне это никогда не требовалось. Поэтому я даже не знаю, надо ли это делать сейчас.
> зачем писать на том, что тебя ограничивает
Во-первых, любой язык ограничивает. Любая среда/платформа ограничивает. Мы просто выбираем то, в чём ограничений меньше лично для нас. И поэтому наш спор - спор о вкусах, и он принципиально неразрешим. Все останутся при своём всё равно.
Во-вторых, развитие рождается из преодоления ограничений. Когда нет ограничений - нет и развития. Эта истина доказана не только в кодинге, и не столько в кодинге, сколько в куче других областей человеческого знания.
>Любая среда/платформа ограничивает
но мы не выбираем другой язык. мы внутри одного языка и плафтормы. просто выбираем гуи фреймворк. И винформс МЕНЕЕ ГИБКИЙ
померяемся количеством языков? сбежишь в ужасе
впрочем причем тут языки если мы говорим про один язык. тебе просто хотелось сманеврировать, но вышло уныло
для зумеров - WPF потеснил винфорс именно благодаря своей концепции lookless контролов. То есть позволял простыми средствами сделать прогрессбар в кнопке в комбобоксе круглый без смс сиськи
а не пердолится в онпаинт или же покупать платные контролы.
винформс чисто по природе никогда не сможет в это. вот просто никогда.
> для зумеров - WPF потеснил винфорс именно благодаря своей концепции lookless контролов. То есть позволял простыми средствами сделать прогрессбар в кнопке в комбобоксе круглый
Еще раз:
>>92993
> Я мокрописечки не писал, мне это никогда не требовалось. Поэтому я даже не знаю, надо ли это делать сейчас.
Я сколько не пытался, даже в ебанутых случаях, когда решаю сделать: MyObject от которого все наследоваться будут - не выходит больше 3х.
Можете рассказать о своем опыте написания систем, с 5+ уровнями наследования?
>Ограничится доступ к среде разработки программ Visual Studio, а также к Visual C++, Visual Studio Code.
https://tass.ru/ekonomika/20287331
Community версию никто трогать не будет, а облачные сервисы и так хуй оплатишь.
Не понял, они же уже всё приостановили, отменили, запретили и ограничили ещё в 2022.
Для разработки на шарпе достаточно dotnet sdk + vim
SDK лежит на гитхабе под MIT, бери. Если такой шизик и боишься, что закроют - качай, собирай и пользуйся.
А вообще, если так уж боишься - бери русский-православный ДРАКОН и ищи вакансии)))
>Можете рассказать о своем опыте написания систем, с 5+ уровнями наследования?
Пример из EF
ListConcreteRepository
наследуется от:
EfListProjectionRepositoryBase<TDbContext, TItem, TItemId, TParameters>
наследуется от:
EfListProjectionReaderRepositoryBase<TDbContext, TItem, TParameters>
наследуется от:
EfListProjectionReaderRepositoryBase<TDbContext, TSourceItem, TTargetItem, TParameters>
наследуется от:
EfRepositoryBase<TDbContext, TItem>
> бери русский-православный ДРАКОН и
ДРАКОН не самостоятелен. Я же написал об этом в клаус-треде. Он по факту сам ни во что не компилируется, он из нарисованных схем генерирует текст на си.
Как принять строку параметров в которой есть /#tgWebAppData=query_id
# - решётка руинит все, я даже не могу попасть по адресу /zalupa#WebAppData
Этот параметр выставляет телеграм при передаче параметра WebAppData
Если без этой модной хуйни а просто разобрать вот так param = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query);
Там тупо пусто в uri.Query нихуя нету, # - решетка все отсекает.
Можно конечно через ЖС достать, но бля неужели как то полегче нельзя то?
Вот я хочу создать проект в котором у меня WebAssembly клиент и сервер к нему.
Все страницы полностью WebAssembly и загружаются на клиент. Юзер будет работать в клиенте изредка клиент будет делать запросы к WebApi и обновлять данные.
Дак вот я создаю проект Auto Создаётся клиент и сервер. Я чет пытаюсь перенести всё в клиент но не получается. Ошибка 2 эндпоинта "/" у меня, нихуя не понимаю что менять что убирать.
2 проекта в одном решении как ты говорил легче в разработке, 1 кнопкой можно запускать.
Можно сделать так. Простой WebAssembly проект отдельный, его разрабатываем, и отдельный Web Api проект на который приходят запросы. Но как мне кажется не сильно удобно.
Вот сейчас у меня тестовый Auto проект я захожу на страницу с WebAssembly но соединение с сервером у меня есть хз почему. Я предполагаю что App.razor грузится с сервера а тело страницы с WA. Как перенести я хз.
Подскажи плиз как сделать что бы было по красоте то.
У меня всё упирается в то что бы снизить максимально нагрузку на сервер. Мини игра будет играться на клиенте а результаты отправлять на сервер. Если играть на сервере то уж очень дохуя нужно будет делать расчётов и держать подключения не резонно так как нет денег на дорогой сервер а я рассчитываю что будет дохуя людей.
Подсоби плиз.
И я не совсем понимаю во что Auto проект компилируется. Предполагаю что BlazorWebASPS.dll отдаёт BlazorWebASPS.Client.dll клиенту. Сложна вкатываться в новую технологию то(
Можешь показать что у тебя в App.razor?
>>95688
Контроллеры ты можешь и в свой серверный проект добавить, да и вообще что угодно из ASP.NET, создай проект с шаблоном Web API и глянь че там в builder и app добавляется в Program.cs, можешь потом Swagger для удобства подключить.
Соединение у тебя есть по двум возможным причинам:
1. У тебя в браузере не был закэширован рантайм и приложение в режиме Auto запустилось на серверном рендере, если сильно нужно и клиент готов подождать можешь настроить приложение для режима WebAssembly.
2. При дебаге через студию поддерживается как минимум одно подключение для непосредственно дебага, попробуй через Publish собрать проект и посмотреть что там будет.
Бля ну я тупень, на релизе подключений нет. А я уже отдельно вебАпи начал пилить(
Ладно всё равно всё надо перенести в чистый проект.
Просто пиздец как всё не понятно и не логично.
Проект веб асембли компилится в одно, Ауто вроде как и веб асембли и сервер компилится в другое, сервер в третье, небось гибрид еще в четвёртое.
>Можешь показать что у тебя в App.razor?
Не покажу уже(
Я уже забыл как я там пытался все перенести, и отменил все действия.
Думаю всё таки отдельно проект с WebApi и отдельно под него клиент на WebAse,bly буду делать что бы когда что то я не так сделал в проекте то пришлось бы переписывать половину.
Зато ты получил ценный опыт о том, как важно держать данные отдельно от кода, и как важно делать код, который ничего не знает о соседних участках кода.
но только после меркуриала.
Так aspnet когда поднимает сервер берет порт и доменное имя из конфигов, конкретно из launchSettings.json. Создавай конфигуратор на этом файле и пропихивай в хендлер/сервис.
Вот есть нжинкс конфиг
В нём локации
location / - работает нормально
location /api/ - нихуя не работает, приложение по site.com/api/test/ не открывается. Когда вешаю это приложение на / то site.com/api/test/ открывается.
Я уже блять по разному /api /api/ api/ api пробывал нихуя.
Как пофиксить эту поебенить?
Смысл в том что по / и остальным адресам где нет /api/ открывается одно приложение а с /api/ другое
Приколная структура получается
Бля, точно. Спасибо. Я что-то вообще забыл про это
Паттерн Сеттер.
Типа такого?
> builder.build(out buildresult br).configure(out configresult cr).connect(out connectionresult cnr);
> if (!cr.isConfigured()) { rebuild(); }
Как эту хуету отключить?
IFormFileCollection files = Request.Form.Files;
MAUI это замена всем хамаринам\wpf\winform\UWP и прочему и теперь это "всё в одном"? А то формально то winforms в 2006 еще приуныл, wpf в 2012, UWP как в 2015 вышла так и не взлетела. MAUI 2022 поэтому считается актуальной или всё еще нужно духов wpf всяких призывать?
Даже винформы бывает нужно
Прдожди года 4, MS высрет еще́ один фреймворк для гуя, а MAUI станет легаси.
Maui это абстракция над нативными гуями, в случае винды это winui. Так как winui кривая тормозящая поделка, то и maui будет ничем не лучше. Wpf в целом неплохой выбор, его даже обновляют временами. добавили диалог выбора папки в net 8. Также и uwp, хоть и забросили, но это все еще самый производительный и стабильный фреймворк для винды. Впрочем и то и другое нахуй не нужно, когда есть Avalonia UI.
> и другое нахуй не нужно, когда есть Avalonia UI
Вопрос закрыт последним постом в ищье:
https://github.com/AvaloniaUI/Avalonia/issues/3023
Собственно что такого? Авалония кроссплатформенна, поэтому имеет свой дизайн контролов, а не подстраивается под системный. Но на том же гитхабе есть набор fluent стилей.
> имеет свой дизайн контролов, а не подстраивается под системный
Темы - это системная задача, это задача ОС. Я хочу в ОС выставить серобуромалиновую тему и ожидаю, что все приложения станут серобуромалиновыми, но тут я открываю мокропиську наговняканную на говнолонии, а у неё вендовый срюент, хотя я сижу на линухе.
Нет, внешний вид приложения это задача приложения. Задача ОС отобразить окно, все остальное ее не касается.
> сама идея того, что приложения должны подстраиваться под ос, сугубо зумерская
> зумер аппелирует к невежеству
Забавный зумер.
> MAUI ответ нормальный дали
> никто нахуй не пользуется
ЗЫС.
> Какой стек вообще сейчас по шарпу
99% посетителей пилят бэк.
Фронт весь в вебе на жс.
Вот к примеру юзер зашёл на сайт, клиент закачался, начал пользоваться сайтом. Потом закрыл сайт. Есть ли время жизни у клиента? Если юзер через минуту зайдет то что будет? Клиент снова будет закачан либо будет использован старый? Как я могу подать сигнал что нужно перекачать клиент? У меня только Blazor WebAssembly приложение + web api
Клиент умирает вместе с закрытием вкладки браузера. Сборка хешируется на клиенте. Узнает от обновлении по хешам, которыми браузер обменивается с сервером во время загрузки странички.
Уточню, что я про 8 блазор говорю, там все именно так. Но первое утверждение для любого васма верное.
А как можно передавать инфу о юзере из страницы в страницу?
Вот есть у меня класс User. В нём хранятся данные пользователя, ну там счёт очки деньги и тд и тп, как только юзер зашёл на главную его профиль загрузился. Потом он к примеру переходит в страницу shop, в параметре компонента передать User ? Далее он в shop что то купит, будет отправлен post запрос на сервер, там будет списание проверка и в ответе придёт новый User в замен старого. А если юзер нажмёт кнопку назад? Как передать в прошлый компонент параметр?
Через параметр нормально. Можно через синглтон вью модель - на васме все сингл тон, так что можешь не париться за лайф тайм сервисов.
Создай евент, подпиши на него все компоненты, которые как-то взаимодействуют со стейтом юзера. В хендлере этого евента вызывай StateHasChanged(). Дергай эвент, когда модель юзера меняется. Таким образом, любой компонент, который тронул юзера, сообщит всем остальным компонентам, что им нужно перерисоваться.
Вот у тебя сервис UserService:
User User {get; set;} = null!;
Action UserHasChanged {get; set;} = null!;
В OnInitializedAsync() индекса ты делаешь:
var response = await httpClient.GetAsync("/getUser");
UserService.User = await response.Content.ReadAsJsonAsync<User>();
if (UserService.User is null) { //приложухой пользоваться не даешь - показываешь оверлей, что у тебя что-то сломалось, приходите позднее }
Компонент, который что-то делает с юзером инициализируется OnInitialized(), там у тебя:
UserService.UserHasChanged += () => {
CurrentUser = UserService.User;
StateHasChanged();
};
[Inject] UserService UserService {get; set;} = null!;
ComponentName.User CurrentUser {get; set;} = null!; // к этому проперти у тебя привязаны контролы в этом компоненте. (можно привязаться к UserService.User, но тогда new для юзера делать нельзя)
Пользователь внес изменения и нажал Ок:
<Button Text="Ok" @onclick=@(OnOkClicked)>
ComponentName.OnOkClicked()
{
UserService.UserHasChanged?.Invoke(); //все инициализированные компоненты, подписанные на этот делегат обновят ссылку на юзера и стейт своих контролов
// опционально закрываешь текущий оверлей, который ответственный за показ компонента ComponentName
}
Правда, если используешь NavigationManager() и прыгаешь по пейджам, то у тебя не SPA и этот подход тебе не подходит. Переделывай на SPA или пользуйся квери параметрами или на каждой страничке переспрашивай юзера у сервера и в кнопке Ок пости юзера обратно.
Вот у тебя сервис UserService:
User User {get; set;} = null!;
Action UserHasChanged {get; set;} = null!;
В OnInitializedAsync() индекса ты делаешь:
var response = await httpClient.GetAsync("/getUser");
UserService.User = await response.Content.ReadAsJsonAsync<User>();
if (UserService.User is null) { //приложухой пользоваться не даешь - показываешь оверлей, что у тебя что-то сломалось, приходите позднее }
Компонент, который что-то делает с юзером инициализируется OnInitialized(), там у тебя:
UserService.UserHasChanged += () => {
CurrentUser = UserService.User;
StateHasChanged();
};
[Inject] UserService UserService {get; set;} = null!;
ComponentName.User CurrentUser {get; set;} = null!; // к этому проперти у тебя привязаны контролы в этом компоненте. (можно привязаться к UserService.User, но тогда new для юзера делать нельзя)
Пользователь внес изменения и нажал Ок:
<Button Text="Ok" @onclick=@(OnOkClicked)>
ComponentName.OnOkClicked()
{
UserService.UserHasChanged?.Invoke(); //все инициализированные компоненты, подписанные на этот делегат обновят ссылку на юзера и стейт своих контролов
// опционально закрываешь текущий оверлей, который ответственный за показ компонента ComponentName
}
Правда, если используешь NavigationManager() и прыгаешь по пейджам, то у тебя не SPA и этот подход тебе не подходит. Переделывай на SPA или пользуйся квери параметрами или на каждой страничке переспрашивай юзера у сервера и в кнопке Ок пости юзера обратно.
>если используешь NavigationManager() и прыгаешь по пейджам, то этот подход тебе не подходит
Уточню, что для васма это может быть не точно - там скойпед сервисов нет, а синглтону плевать на NavigateTo(). Так что, лучше затести этот момент сам.
>на васме все сингл тон
Наверное вопрошающий не воспользуется этой информацией в рамках своей задачи, но Transient там работает как и должен.
SPA в смысле у меня одна страница "/" и на ней только компоненты меняются? Вроде как нет, у меня будут разные страницы.
Я вот сейчас подумал можно попробовать сделать типо сервис AddSingleton с хранилищем User как ты писал выше. А потом все действия проходят через методы этого User. Например покупка чего лобо User.buy("zalupa"), делаю запрос на апи, покупаю возвращаю обновлённого юзера, обновляю юзера и после делаю StateHasChanged(), на странице все должно поменятся, и если юзер переходит на другую страницу то снова дёргаю с AddSingleton.
Я еще плохо понимаю как относится к этому веб ассембли, вроде похоже на обычное приложение а вроде и нет.
Спасибо за советы.
Бля и я забываю что можно создавать свои классы, и ебеню все в @code{}
Ну в общем в рамках васма - у тебя в любом случае spa и NavigationManager погоды не сделает. Стейты сбрасываться не будут и ты можешь без проблем пользоваться статическими классами. Но это лучше затестить.
Поправите, если я хуйню пишу.
Если работаешь один над проектом, то нормально. Если не один, то никто кроме тебя пользоваться не будет и получится, что все в разнобой.
Жиза, меня это очень обижает. Будто коллеги мне доверяют моему коду...
Давайте правильно перекатим, пожалуйста, у меня тред тормозит. Сжальтесь!
Есть данные которые отправляются на Апи. Клиент может с разным RPS отправлять данные. К примеру клиент отправляет 1 RPS, но сервер тормозит и не принимает так быстро, запросы падают в очередь, очередь продвигается по мере ответов сервера.
Так то в голове я примерно представляю как это сделать но мб уже готовое есть.
Это копия, сохраненная 4 мая в 12:13.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.