«игнорирование» P / Invoke при работе на Mono - PullRequest
5 голосов
/ 19 августа 2009

У меня есть приложение WinForms, которое я хочу запустить в Mono в какой-то момент. Однако он использует P / Invoke против user32.dll, что вызовет очевидные проблемы.

Тем не менее, это не критическая функциональность, а просто некоторые вещи. Поэтому я хотел бы игнорировать это при запуске Mono.

Я знаю, что мог бы просто использовать директиву #if, но тогда я должен предложить две разные сборки, что плохо. Я знаю, что могу проверить во время выполнения, работаю ли я в Mono, но это не поможет мне удалить объявления для функций.

Итак, я задаюсь вопросом: есть ли способ, которым я могу сказать: «Если работает Mono, игнорируйте это полностью»? Если это помогает: материал P / Invoke находится в отдельном файле .cs и реализован как частичный класс.

Исходный код, о котором идет речь, находится здесь: http://pastie.org/588940
Это часть моей Основной формы, переопределяющая сообщение WndProc для добавления элемента в системное меню. (Некоторые другие вещи обрезаны). Моя проблема в том, что, хотя с WndProc все просто, я не знаю, что делать с двумя частными объявлениями extern - могу ли я поместить их в другой (статический) класс, который я никогда не вызываю в Mono? Или это будет русская рулетка?

Ответы [ 4 ]

8 голосов
/ 19 августа 2009

Почему бы не инкапсулировать зависящие от платформы вещи в интерфейсе, а затем найти способ «правильной» реализации для текущей платформы. Тогда вызывающий код может использовать его беспечно, и вы можете постепенно заполнять биты для запуска на моно, как и когда вы хотите. Я бы по крайней мере надеялся , что если вы даже никогда не загрузите класс, содержащий биты P / Invoke, у вас все будет в порядке ...

EDIT:

Я не понимаю, почему этот подход не должен работать, хотя вам может даже не понадобиться фабрика. Вот что я бы сделал:

MainForm.cs:

PlatformServicesFacade.InitializeSystemMenu();

IPlatformServices.cs:

public interface IPlatformServices
{
    void InitializeSystemMenu();
}

MonoPlatformServices.cs:

public class MonoPlatformServices : IPlatformServices
{
    // Prevent early type initialization
    static WindowsPlatformServices() {}

    public void InitializeSystemMenu()
    {
        // Maybe log what you would have done?
    }
}

WindowsPlatformServices.cs:

public class WindowsPlatformServices : IPlatformServices
{
    // Prevent early type initialization
    static WindowsPlatformServices() {}

    public const Int32 SystemMenuAboutSWikiId = 1000;
    [DllImport("user32.dll")]
    private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
    [DllImport("user32.dll")]
    private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, 
                                          Int32 wFlags, Int32 wIDNewItem,
                                          string lpNewItem);

    public void InitializeSystemMenu()
    {
        const Int32 MF_SEPARATOR = 0x800;
        const Int32 MF_BYPOSITION = 0x400;

        IntPtr systemMenuPtr = GetSystemMenu(Handle, false);
        InsertMenu(systemMenuPtr, 5, MF_BYPOSITION | MF_SEPARATOR, 0, "");
        InsertMenu(systemMenuPtr, 6, MF_BYPOSITION, SystemMenuAboutSWikiId, 
                   "About SWiki...");
    }
}

PlatformServicesFacade.cs:

public class PlatformServicesFacade
{
    private static readonly IPlatformServices services;

    static PlatformServiceFacade()
    {
        services = RunningOnWindows() ? new WindowsPlatformServices()
            : (IPlatformServices) new MonoPlatformServices();
    }

    public static void InitializeSystemMenu()
    {
        services.InitializeSystemMenu();
    }
}

Я думаю , что должно работать ... если это не так, пожалуйста, сообщите нам, что идет не так:)

4 голосов
/ 19 августа 2009

Некоторые свойства среды, вероятно, содержат эту информацию, например System.Environment.OSVersion.Platform. Или используйте if (Type.GetType ("Mono.Runtime")! = Null)

Смотрите "Как определить платформу выполнения?" и «Как я могу определить, работает ли я в Mono?»: http://www.mono -project.com / FAQ: _Technical

2 голосов
/ 19 августа 2009

Я думаю, ваша лучшая ставка будет M / Invoke от парней из Mono Это все еще довольно новый (только в Mono SVN). Но я уверен, что они бы с удовольствием помогли получить его в Mono Distribution:)

2 голосов
/ 19 августа 2009

Проверка времени выполнения кажется жизнеспособным решением. Есть ли причина, по которой вы хотели бы удалить объявления функций P / Invoke, если они работают под Mono, даже если они никогда не используются?

...