Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.79/14: Рейтинг темы: голосов - 14, средняя оценка - 4.79
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2

Как определить из кода библиотеки Standard платформу приложения (Forms, WPF, UWP, Framework, Core и т.д.)?

03.01.2024, 18:13. Показов 3015. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть некий код в библиотеке типа Standard 2.0
В зависимости от типа приложения нужно по разному реализовать некоторые тонкие моменты.
Типовой подход: создание разных библ (сборок) под разные платформы.
Но хотелось бы избежать этого.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.01.2024, 18:13
Ответы с готовыми решениями:

UWP и Entity framework core
Добрый день. Пытаюсь установить Entity framework core из NuGet для UWP Не выходит Рис 1.

Что лучше выбрать приложения WPF(.Net framework) или WPF(microsoft)
Сайт почему то ругается на слово Майкрософт а заголовке так что в заголовке она на английском а вообще она на русском при создании проекта,...

VS2019, в чем разница, приложение WPF (.Net Framework) и App WPF (.NET Core)
Открыл сейчас VS2019, чтобы "создать новый проект" и не знаю на какую кнопочку нажать (я не программист, но потихоньку что-то делаю...

21
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,593
Записей в блоге: 2
03.01.2024, 18:33
А разве Forms это не тот же Framework или Core, в зависимости от версии языка?

А по коду помоему не определить. Это же незря добавляют в код в виде метакода типа "#if DEBUG".
Читать тут: C# preprocessor directives
Поэтому если большое желание есть этим управлять в глубоком коде, то можно в этих блоках набодяжить свои переменные которые будут иметь нужные значения.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
03.01.2024, 18:56  [ТС]
Цитата Сообщение от HF Посмотреть сообщение
А разве Forms это не тот же Framework или Core, в зависимости от версии языка?
Пример.
Командe для WPF лучше автоматически подписаться на CommandManager.RequerySuggested. Для остальных платформ этого не следует делать.
Так же есть различия в маршалинге событий из разных потоков.

Реализовать эти различия я смогу. Но вот неуверен насчёт надежного детектирования платформы приложения в рантайм.
0
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,593
Записей в блоге: 2
03.01.2024, 19:26
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Командe для WPF лучше...
Директивы компиляторные. Только они точно скажут под что сборка была.
А вот то что у вас в рантайме разный код "лучше" выполнять. То я бы сразу смотрел в сторону явного переноса реализации. Ну типа чтобы в каждом платформенном проекте был метод (одного интерфейса) для какой-то настройки. И тогда в рантайме то он точно же должен вызывать верную реализацию. Ну а там уже делайте что лучше в этой платформе.
1
 Аватар для aenye
304 / 186 / 45
Регистрация: 05.07.2018
Сообщений: 580
04.01.2024, 14:01
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Командe для WPF лучше автоматически подписаться на CommandManager.RequerySuggested. Для остальных платформ этого не следует делать.
Есть ощущение, что тогда это уже не будет являться библиотекой общего назначение (которую Вы, судя по всему, хотите реализовать).
Возможно, более оптимальным вариантом будет выпустить базовый пакет с абстракциями, а потом несколько пакетов с реализациями этих абстракций (с зависимостью от пакета с ними). Как мне кажется, так конечному пользователю было бы удобнее. Нужно просто установить пакет для своей платформы (WPF, WF, etc), чем ставить тот же один пакет, но заточенный под все подряд, и пытаться угать, не сломается ли ничего конкретно в его случае.
Если делаете только для себя, то вариант с несколькими пакетами будет выглядеть еще более оптимально, потому что минусы в виде строго одинакового версионирования нескольких пакетов, поддержки валидации корректных версий зависимостей и т.д. отпадают.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
04.01.2024, 15:12  [ТС]
Цитата Сообщение от aenye Посмотреть сообщение
Возможно, более оптимальным вариантом будет выпустить базовый пакет с абстракциями
Пример.

Есть ViewModel. Логика полностью едина для любой платформы.
Но вот реализация INPC и Комманд несколько различны. Так же различается синхронизация INCC.

Можно, конечно, сделать такую VM платформозависимой и компилировать по разному для разных платформ.
Но вот обдумываю и вариант единой сборки в которой в рантайм будет определяться платформа UI и подтягиваться нужные реализации.
0
1339 / 919 / 264
Регистрация: 08.08.2014
Сообщений: 2,763
04.01.2024, 17:51
Штатными средствами никак, вроде. Разве что лезть напрямую в память и искать там характерные сборки по сигнатуре. Менее упоротый вариант - пытаться в try/catch через рефлекшн инстанциировать специфичные для каждой платформы типы. Упал - значит не та платформа, успешно - значит та. Написать отдельные методы типа 'IsWPF', 'IsWF' и т.п., дёргать их на старте, сохранять результа и ок (правда, там есть нюанс - в WPF-приложении будут в т.ч. и WF-типы).

Добавлено через 8 минут
Ну т.е. что-то типа:
C#
1
2
3
4
5
6
7
8
9
10
11
12
    public static bool IsWPF()
    {
        try
        {
            Activator.CreateInstance("PresentationFramework", "System.Windows.Window");
            return true;
        }
        catch
        {
            return false;
        }
    }
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
04.01.2024, 23:09  [ТС]
Цитата Сообщение от kotelok Посмотреть сообщение
Написать отдельные методы типа 'IsWPF', 'IsWF' и т.п., дёргать их на старте,
Я что-то подобное реализовал.
"Дергаю" типы и их члены из сборок специфичных для платформы (точно не помню, но вроде эти):
System.Windows.Application.Current - PresentationFramework.dll
System.Windows.Forms.Application.OpenFor ms - System.Windows.Forms.dll
Windows.UI.Xaml.Application.Current - Windows.UI.Xaml.dll

Нужно ещё добавить для Xamarin, WinUI, Avalonia, UNO....
Слишком громоздко получается. Поэтому и подумал: может есть что-то попроще?
0
Эксперт .NET
 Аватар для Usaga
14093 / 9310 / 1349
Регистрация: 21.01.2016
Сообщений: 34,983
05.01.2024, 06:32
Элд Хасп, тут или через рефлексию искать "специальные" типы соответствующие платформе, что полная лажа, или собирать под каждую платформу отдельную версию сборки.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
05.01.2024, 08:28  [ТС]
Цитата Сообщение от Usaga Посмотреть сообщение
или через рефлексию искать "специальные" типы соответствующие платформе, что полная лажа,
Начал делать именно так, и самому не нравится такое решение. Поэтому и задал вопрос.

Цитата Сообщение от Usaga Посмотреть сообщение
или собирать под каждую платформу отдельную версию сборки.
Вот этого и хотелось избежать, так как вся разница в логике это будет только подтягивание разных базовых типов. Вся остальная логика будет единой.
Условные пример:
C#
1
2
3
4
public class ViewModel: CommonWpf.ViewModelBase
{
    public class IRelayCommand SomeCommand {get;} = new CommonWpf.RelayCommand(....);
}
C#
1
2
3
4
public class ViewModel: CommonUwp.ViewModelBase
{
    public class IRelayCommand SomeCommand {get;} = new CommonUwp.RelayCommand(....);
}
Пока склоняюсь к варианту с фабрикой команд. И отдельным расширяемым классом определения платформы. В фабрике будут методы настройки возвращаемых типов. По умолчанию будет получать настройки от класса определяющего платформу.

Но тоже пока сомневаюсь:
1)Получается всё таки несколько громоздко;
2) Такой способ не подойдёт для ViewModelBase.
0
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,593
Записей в блоге: 2
05.01.2024, 11:37
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вот этого и хотелось избежать, так как вся разница в логике это будет только подтягивание разных базовых типов. Вся остальная логика будет единой. Условные пример: ...
Наверное я плохо описал вариант, но представлял и советовал это.

А если точнее то ещё чуть дальше.

CommonUwp и CommonWpf - это ведь как раз тот "сервис" который
- должен иметь общий интерфейс. В данном случае для метода RelayCommand
- интегрирован в ViewModel (не CommonUwp.ViewModelBase или CommonWpf.ViewModelBase)

а DI регистрация этой реализации должна выполняться разумеется в самом приложении, которое у вас и будет этим самым - UWP или WPF или XXX.
1
1167 / 885 / 517
Регистрация: 09.04.2014
Сообщений: 2,095
05.01.2024, 12:10
а почему бы не заставить пользователя правильно инициализировать библиотеку перед использовагием и не городить огород с автоматическим распознаванием типа приложения?
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public enum ApplicationType { None, WinForms, UPF }
public static class LibConfiguration
{
    static ApplicationType _AppType = ApplicationType.None;
    internal static ApplicationType AppType
    {
        get
        {
            if (_AppType == ApplicationType.None)
                throw new Exception("Not inited. Call LibConfiguration.Init method first");
            return _AppType;
        }
    }
    public static void Init(ApplicationType appType)
    {
        if (_AppType != ApplicationType.None)
            throw new Exception("Already inited");
        _AppType = appType;
    }
}
1
HF
 Аватар для HF
1303 / 882 / 199
Регистрация: 09.09.2011
Сообщений: 2,593
Записей в блоге: 2
05.01.2024, 12:55
Цитата Сообщение от nedel Посмотреть сообщение
а почему бы не заставить пользователя правильно инициализировать библиотеку перед использовагием и не городить огород с автоматическим распознаванием типа приложения?
Это то что я тоже предлагал выше.
Цитата Сообщение от HF Посмотреть сообщение
Поэтому если большое желание есть этим управлять в глубоком коде, то можно в этих блоках набодяжить свои переменные которые будут иметь нужные значения.
Но это тоже будет "городить огород", так как использование таких переменных - это постоянное их использование. Это только в вашем примере только один класс. А если весь код забит такими "развилками" для разных платформ.

Поэтому лучшее решение - по возможности максимально глубоко затащить использование под конкретную платформу в конкретный проект, где не нужны никакие ифы и определения платформ. Она уже знает кто она и вызовет только то что знает.
1
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
05.01.2024, 14:03
Цитата Сообщение от Элд Хасп Посмотреть сообщение
В зависимости от типа приложения нужно по разному реализовать некоторые тонкие моменты.
Стандартный подход в таких случаях — как говорили выше, делать отдельные сборки под разные платформы.
Наглядный пример — CommunityToolkit.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Командe для WPF лучше автоматически подписаться на CommandManager.RequerySuggested.
По поводу "лучше" — это спорно.

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Для остальных платформ этого не следует делать.
Боюсь даже подумать почему оттуда этот функционал убрали!

Если серьезно, то слепая подписка на RequerySuggested — так себе затея. В мало-мальски сложном интерфейсе оно может привести к лагам, потому лучше оставить эту подписку на совести пользователя класса.
В своем пакете YAMVVML.WPF можете поставлять реализацию CommandFactory, которая будет делать подписку с возможностью отказаться:
C#
1
2
3
4
5
6
7
8
9
ICommand CreateRelayCommand<T>(Action<T> execute, Predicate<T>? canExecute = null, bool raiseCanExecuteChangedOnRequerySuggested = true)
{
   var command = new RelayCommand<T>(execute, canExecute);
 
   if (raiseCanExecuteChangedOnRequerySuggested)
      CommandManager.RequerySuggested += (o, e) => command.RaiseCanExecuteChanged();
 
   return command;
}
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
05.01.2024, 15:13  [ТС]
Цитата Сообщение от kolorotur Посмотреть сообщение
В мало-мальски сложном интерфейсе оно может привести к лагам
Согласен.
Но CanExecute должен быть быстрым.
В WPF ревалидация делается через подписку на CommandManager.RequerySuggested.
В UWP, как я понял, даже без подписки, при изменениях в GUI автоматически ревалидируются все команды.

Так что отсутствие подписки не означает что, на CanExecute можно вешать что угодно.

Цитата Сообщение от kolorotur Посмотреть сообщение
можете поставлять реализацию CommandFactory, которая будет делать подписку с возможностью отказаться:
Тоже об этом думаю.
Но пока нет для себя принятия решения - какой вариант реализации лучше.
Цели конкурировать с распространёнными пакетами нет.
Это скорее будет некий учебный проект на котором можно посмотреть работу "внутренностей".
В том числе, продемонстрировать реализацию платноформонезависимых (Standard) Модели и ViewModel.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
05.01.2024, 15:25  [ТС]
Цитата Сообщение от nedel Посмотреть сообщение
а почему бы не заставить пользователя правильно инициализировать библиотеку перед использовагием и не городить огород с автоматическим распознаванием типа приложения?
Вариант с инициализацией, на мой взгляд, это не замещение авторазпознавания, а дополнение к нему.

Цитата Сообщение от HF Посмотреть сообщение
Это только в вашем примере только один класс.
Имеющие значения отличия на уровне взаимодействия View и ViewModel это разная реализация маршалинга событий не из UI потока: INPC.PropertyChanged, ICommand.CanExecuteChanged, INCC.CollectionChanged. Возможно ещё и для IBindingList.
И подписка на CommandManager.RequerySuggested для WPF.

Есть ещё немного по разному обращение к основному UI потоку. Но у меня пока нет решения насколько это нужно в слоях ниже View. Даже если делать подобное, то наверное нужно через внедрение контекста синхронизации, а не получения Диспетчера и т.п. классов.

Больше отличий я пока не вижу.
Но будут свойства, которые при желании, можно будет использовать и для других классов.
0
Эксперт .NET
 Аватар для Wolfdp
3789 / 1766 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
06.01.2024, 21:36
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Командe для WPF лучше автоматически подписаться
Мммм... а если внутри WPF вызывается окно WinForms (и наоборот) -- это считается всё ещё как (не)WPF приложение, или должно детектить прям в каком контектсте вызывается?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
06.01.2024, 22:14  [ТС]
Цитата Сообщение от Wolfdp Посмотреть сообщение
а если внутри WPF вызывается окно WinForms (и наоборот)
Пока для меня это слишком сложно. Даже на уровне просто определения контекста синхронизации.
С потоком может быть связан, вроде, только один контекст синхронизации SynchronizationContext.Current.
Но у Форм это WindowsFormsSynchronizationContext, а у WPF DispatcherSynchronizationContext.
0
HF
07.01.2024, 01:04

Не по теме:

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Это скорее будет некий учебный проект на котором можно посмотреть работу "внутренностей".
В том числе, продемонстрировать реализацию платноформонезависимых (Standard) Модели и ViewModel.
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Пока для меня это слишком сложно. Даже на уровне просто определения контекста синхронизации.
С потоком может быть связан, вроде, только один контекст синхронизации SynchronizationContext.Current.
Но у Форм это WindowsFormsSynchronizationContext, а у WPF DispatcherSynchronizationContext.
Сколько вас читаю, почти всегда возникает мысль о том что вы всё слишком переусложняете. И даже говорил про это. Согласен, сложно доказать сложность, не предоставив простое решение. Но голос моего опыта настойчиво повторяет "Что-то тут не так".
Если для простого проекта вы уже добрались до SynchronizationContext, то это уже далеко не учебный проект. Уже напоминает рождение нового фреймворка.

0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16117 / 11238 / 2887
Регистрация: 21.04.2018
Сообщений: 33,038
Записей в блоге: 2
07.01.2024, 10:16  [ТС]
Цитата Сообщение от HF Посмотреть сообщение
почти всегда возникает мысль о том что вы всё слишком переусложняете. И даже говорил про это.
Возможно.
Но во многом это учёба и для меня самого.

Цитата Сообщение от HF Посмотреть сообщение
Если для простого проекта вы уже добрались до SynchronizationContext, то это уже далеко не учебный проект.
Для Реализации Приложения с GUI использующего многопоточность (на уровне Модели) так или иначе всё равно эту тему придётся поднять.
Если делать под конкретный тип GUI то встанет вопрос внедрения в VM и Модель методов выполнения в основном потоке.
Если делать эти методы универсальными, то оптимальнее всего использовать SynchronizationContext.

Для приложений, в которых нет асинхронности, это, конечно, не нужна и является лишней обузой.

Добавлено через 4 минуты
HF, честно говоря, для меня до сих пор так и остаётся непонятным по какой причине реализация маршалинга сделана на всех платформах по разному.
Например, в UWP что мешало добавить маршалинг INPC? Добавить этот маршалинг можно десятком строк, наверное. Ведь для INCC и команд он есть. Ладно, было бы как-то понятно, если бы не для чего не было. А тут какая-то половинчатая реализация.

Добавлено через 5 минут
То же самое в WPF. Проверку потока для CanExecuteChanged можно сделать пятью строчками. Что мешает их добавить в исходники?
За CollectionChanged даже сказать не знаю что.... Она уже реализована - BindingOperations.EnableCollection. Всего лишь по умолчанию требуется включать её. И для 99.99% задач этого хватит. Её даже выключать потом не надо так как коллекция удерживается по слабой ссылке.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.01.2024, 10:16
Помогаю со студенческими работами здесь

Как повторить кусок кода из WPF в Xamarin forms
Как повторить кусок кода из WPF в Xamarin forms? Создал несколько ContentView со своими viewmodel и хотел чтоб в зависимости от текущей...

Действие при закрытии приложения UWP или WPF
Действие при закрытии приложения c# uwp, wpf. *Сорян за ошибку)*

Что выбрать - WPF .Net Core или WPF .Net Framework + буду работать с SQLite (также интересно какую версию БД выбрать)?
Всем привет. Ниже необязательная предыстория, высказался просто) Тут наконец вновь взялся за мелкую приложуху для Windows 7,...

Как определить в какой версии можно использовать тот или иной метод из UWP библиотеки?
Например, есть код: public DropShadowPanel() { if...

Как сменить целевую платформу NET.Framework?
Всем привет! Вопрос: Имеется ПК под управлением Windows 10. Если верить первому скриншоту, в системе имеется NET.Framework 4.8 При...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение/ Перевод https:/ / **********/ gallery/ thinkpad-x220-tablet-porn-gzoEAjs . . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru