Как определить, создается ли экземпляр класса в консольном приложении или 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