Как определить, создается ли экземпляр класса в консольном приложении или wpf?
Мне нужно написать обертку вокруг стороннего api, который просматривает насосы сообщений и, следовательно, должен обрабатываться по-разному в зависимости от того, создается ли обертка в потоке пользовательского интерфейса (например, в приложении wpf) или нет (например, консольное приложение).
Если он не работает в потоке пользовательского интерфейса, мне нужен диспетчер и реализовать свой собственный насос сообщений.
для этой цели мне нужно знать, создается ли обертка в wpf заявление или нет. Недостаточно определить, происходит ли создание экземпляра в потоке пользовательского интерфейса или нет (как даже в приложении wpf поток, на котором создается обертка, может не быть потоком пользовательского интерфейса).
есть ли способ выяснить, нахожусь ли я в среде wpf или windows form с насосом сообщений или консольным приложением, где я должен реализовать свой собственный насос сообщений?
спасибо
4 ответов
если никакой другой ответ не удовлетворяет вашим потребностям - вы можете использовать отражение, чтобы проверить, если Application.Current
равно null или нет, без прямой ссылки на сборки WPF (и то же самое работает с WinForms):
private static bool IsWpfApplication() {
var type = Type.GetType("System.Windows.Application, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
if (type == null)
return false;
var currentProp = type.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
if (currentProp == null)
return false;
return currentProp.GetValue(null, new object[0]) != null;
}
обратите внимание, что это может загрузить PresentationFramework
dll в текущий домен приложения, даже в консольном приложении. Если это проблема для вас - вы можете сделать то же самое, проверив сборки, уже загруженные в домен приложения:
private static bool IsWpfApplication2() {
var wpfAsm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(c => c.GetName().Name == "PresentationFramework");
if (wpfAsm == null)
return false;
var type = wpfAsm.GetType("System.Windows.Application");
if (type == null)
return false;
var currentProp = type.GetProperty("Current", BindingFlags.Public | BindingFlags.Static);
if (currentProp == null)
return false;
return currentProp.GetValue(null, new object[0]) != null;
}
Я думаю, вам лучше иметь три отдельных пакета.
чтобы сделать его автоматический выбор, вам нужно будет иметь ссылки на оба WPF и WinForms в вашем пакете. Предполагая, наихудших, ваш пакет просто заставил меня импорт и в мое консольное приложение. Другие могут рассмотреть возможность импорта WinForms в наихудшем случае приложения WPF, а другая группа людей может делать WinForms, потому что они не могут получить доступ к WPF (и поэтому вы просто вырезать их от использования вашего пакета).
есть ли способ выяснить, нахожусь ли я в среде wpf или windows form с насосом сообщений или консольным приложением, где я должен реализовать свой собственный насос сообщений?
вы можете проверить, есть ли окно верхнего уровня:
if (Process.GetCurrentProcess().MainWindowHandle != IntPtr.Zero)
//WPF
MainWindowHandle
должен возвращать дескриптор при условии, что приложение WPF имеет главное окно.
вы также должны иметь возможность использовать родной GetConsoleWindow функция, чтобы определить, находитесь ли вы в контексте консольного приложения.
Это может сработать:
public static void Main(string[] args)
{
var application = Application.Current;
Console.WriteLine($"Application is {(application == null ? "null": "not-null")}");
Console.ReadKey();
}
требует ссылок на PresentationFramework и, согласно Resharper, WindowsBase и System.В XAML