C # Mono / .NET разностное CAD программное обеспечение - PullRequest
1 голос
/ 16 декабря 2011

Хорошо, я постараюсь сделать все возможное, но я думаю, что мой английский все еще слишком плох, когда речь идет о сложных предметах / фразах.

Мне нужно построить класс (а пока это не такstatic), который извлекает информацию о внешнем приложении (программное обеспечение доступно на ПК пользователя).

Класс Linux был действительно прост для программирования, но теперь я должен реализовать его в Windows.

В основномЯ столкнулся с некоторыми трудностями при чтении реестра x64 из версии моего приложения x86: вы можете сделать это только с помощью [DllImport ("advapi32.dll")].

С самого начала я знал, что удаление программного обеспечениясильно зависит от целевой ОС, поэтому я создал 4 класса:

public abstract ExternalApplications, который определяет некоторые основные методы и выводится из ExternalApplicationsWin, ExternalApplicationsMac и ExternalApplicationsUnix.

Приложение Inmy. Я создаю экземпляр ExternalApplications и назначаю его, переключая тип операционной системы:

ExternalApplications ex = null;

switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT:
   goto default;
case PlatformID.MacOSX:
   _ex = new ExternalApplicationsMac(); break;
case PlatformID.Unix:
   _ex = new ExternalApplicationsUnix(); break;
default:
   _ex = new ExternalApplicationsWin(); break;
}

Таким образом, вызов метода будет автоматически отправлен наright ExternalApplicationsXXX type.

Теперь, введя [DllImport("advapi32.dll")], я обязан:

  • изменить структуру класса (на статический extern)
  • это, вероятно, затормозитМоно-компиляция на Unix / Mac OS X (с DllNotFoundException)

Существует несколько вариантов: (1) я могу создать 3 параллельных проекта (.cproj) с одинаковым именем целевой сборки для Linux, Macи винда.Проекты будут содержать те же классы и методы, чтобы я мог без проблем ссылаться на них внутри своего приложения.

Эта опция отстой, ей не хватает автоматизации: все делается вручную.

(2)Я могу выполнить превентивное исключение кода «DllImport», используя директивы C #, такие как

#if !MONO
...
#endif

Я уверен, что есть много других методов, таких как DLLMAP и другие.Я думаю, что более опытные программисты скажут мне, что является самым элегантным / надежным решением.

РЕДАКТИРОВАТЬ 1:

Я только что обнаружил, что чтение куста реестра x64 отПриложение x86 возможно, однако только в .NET 4.0 и выше (согласно моему источнику, все еще нужно проверить).

string registryBranchPath = "SOFTWARE\MySoft";
RegistryKey regKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
regKey = regKey.OpenSubKey(registryBranchPath);

Это решает только одну часть моего вопроса, другую часть (относительноВозможность использования DllImport в нестатических классах Windows) еще должна быть подтверждена / протестирована.

Ответы [ 2 ]

4 голосов
/ 16 декабря 2011
  1. Ваш класс не должен быть static, только импортированный внешний метод помечается как таковой. Кроме того, импортируемый метод должен быть помечен private, поскольку ничто, кроме класса импорта, не должно вызывать его напрямую.

  2. Вам не нужны какие-либо хитрые трюки при компиляции / разбиение кода, DllImport не проверяется, пока не будет фактически вызван.

Пример из документации MSDN для DllImport:

using System;
using System.Runtime.InteropServices;

class Example
{
    // Use DllImport to import the Win32 MessageBox function.
    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int MessageBox(IntPtr hWnd, String text, 
      String caption, uint type);

    public void MessageBox()
    {
        // Call the MessageBox function using platform invoke.
        MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);
    }
}
0 голосов
/ 17 декабря 2011

Таким образом, окончательное решение для меня будет выглядеть следующим упрощенным фрагментом:

public static class UsageClass
{
    private static ExternalApplications _extApps;

    public static void Initialize()
    {
        _extApps = null;

        switch (Environment.OSVersion.Platform)
        {
            case PlatformID.Win32NT:
                goto default;
            case PlatformID.MacOSX:
                _extApps = new ExternalApplicationsMac(); break;
            case PlatformID.Unix:
                _extApps = new ExternalApplicationsUnix(); break;
            default:
                _extApps = new ExternalApplicationsWin(); break;
        }
    }

    internal abstract class ExternalApplications
    {
        public abstract string[] DoSomething();
    }

    internal class ExternalApplicationsWin : ExternalApplications
    {
        public abstract void DoSomething()
        {
            // Windows code
            RegistryKey regKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                (Environment.Is64BitOperatingSystem) ? RegistryView.Registry64 : RegistryView.Registry32).OpenSubKey("SOFTWARE\MySoft");
            ...

        }
    }

    internal class ExternalApplicationsUnix : ExternalApplications
    {
        public abstract void DoSomething()
        {
            // Unix code
        }
    }

    internal class ExternalApplicationsMac : ExternalApplications
    {
        public abstract void DoSomething()
        {
            // Mac code
        }
    }
} 
...