недостоверные исторические мелочи: "испытание с помощью дыма" прибывает из подводной разработки (наследованный от инфраструктуры), где литеральный дым был бы накачан в оболочку, чтобы видеть, вышел ли какой-либо из него снова, который был бы скорее поразительным отказом для подводной лодки!
Почему бы не инкапсулировать платформенно-зависимый материал в интерфейс, а затем иметь какой-нибудь способ получить «правильную» реализацию для текущей платформы. Тогда вызывающий код сможет беззаботно использовать его, и вы можете постепенно заполнять биты для запуска в 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();
}
}
Я думаю это должно сработать ... если не работает, расскажите, пожалуйста, что не так :)
Некоторые свойства Environment, вероятно, содержат эту информацию, например System.Environment.OSVersion.Platform. Или используйте if (Type.GetType ("Mono.Runtime")! = Null)
См. "Как определить платформу выполнения?" и «Как определить, работает ли я в Mono?»: http://www.mono-project.com/FAQ:_Technical
Проверка времени выполнения кажется жизнеспособным решением. Есть ли причина, по которой вы хотели бы удалить объявления функции P / Invoke, если они работают под Mono, даже если они никогда не используются?
Я думаю, ваш лучший выбор будет M / Invoke от парней из Mono. Он все еще довольно новый (только в Mono SVN). Но я уверен, что они хотели бы помочь с распространением моно :)