我有一个WinForms应用程序,我希望在某些时候在Mono上运行。但是,它正在对user32.dll使用一些P / Invoke,这将导致明显的问题。
然而,这不是一个关键的功能,只是一些风味的东西。所以我想在运行Mono时忽略它。
我知道我可以使用#if指令,但是我必须提供两个不同的程序集,这很糟糕。我知道如果我在Mono中运行,我可以检查运行时,但这不会帮助我删除函数的声明。
所以我想知道:有没有办法可以说“如果运行Mono,完全忽略它”?如果有帮助:P / Invoke内容在一个单独的.cs文件中,并作为Partial Class实现。
有问题的源代码在这里:http://pastie.org/588940
它是我的主窗体的一部分,覆盖WndProc消息以将项添加到系统菜单。 (其他一些东西被剪掉)。我的问题是虽然WndProc的东西很简单,但我不知道如何处理这两个私有的extern声明 - 我可以把它们放到另一个(静态)类中,我从不在Mono上调用它吗?或者那是俄罗斯轮盘赌?
答案 0 :(得分:8)
为什么不在平台中封装依赖于平台的东西,然后有一些方法来获得当前平台的“正确”实现。然后调用代码可以轻松地使用它,并且您可以根据需要逐渐填充位以在Mono上运行。我至少希望如果你从未加载包含P / Invoke位的类,你应该没问题......
编辑:
我不明白为什么这种方法不起作用,尽管你可能甚至不需要工厂。这就是我要做的事情:
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();
}
}
我认为应该有用......如果没有,请告诉我们出了什么问题:)
答案 1 :(得分:4)
某些Environment属性可能包含此信息,例如System.Environment.OSVersion.Platform。或者使用if(Type.GetType(“Mono.Runtime”)!= null)
请参阅“如何检测执行平台?”和“如何检测我是否在Mono中运行?”:http://www.mono-project.com/FAQ:_Technical
答案 2 :(得分:2)
检查运行时似乎是一个可行的解决方案。如果在Mono下运行,你是否有任何理由要删除P / Invoke函数声明,即使它们从未被使用过?
答案 3 :(得分:2)
我认为你最好的选择是来自Mono球员的M/Invoke。它仍然很新(仅在Mono SVN中)。但我确信他们会喜欢帮助将它变成Mono发行版:)