Препроцессор: Получить операционную систему .Net Core - PullRequest
0 голосов
/ 12 сентября 2018

Я пишу класс, который хочу использовать как в Windows, так и в Linux.

Один из методов этого класса - доступ к Реестру Windows

Чего я надеюсь добиться, так это как-то отключить использование этого конкретного метода при использовании машины с Linux.

Прежде всего, я провел некоторое исследование, чтобы выяснить, есть ли что-то для .NetЯдро , которое позволило бы мне проверить, какая операционная система используется, я обнаружил это и достаточно уверен, что это работает.

Когда я внедрил его в свой код при доступе к методу,Я надеялся отключить метод, который обращается к реестру Windows, однако ближе всего я мог получить это с помощью оператора switch, что-то вроде

switch (OS)
{
    case OSX:
    return;

    case LINUX:
    return
}

To return, если операционная система не поддерживаласьэто сработало, однако я тогда подумал, что отключить его от общего доступа было бы гораздо лучше, чем выдать ошибку для операционной системы, которая не поддерживаетсяэтот конкретный метод

Затем я посмотрел на директивы препроцессора , думая, что если я смогу обнаружить и отключить части кода в зависимости от каркасов и т. д., возможно, я мог бы использовать что-то вроде этогочтобы отключить части кода в зависимости от операционной системы таким образом, чтобы их нельзя было вызывать даже при попытке доступа к методу

Я пошел оттуда, чтобы посмотреть, смогу ли я отключить части кода с помощью preprocessor directives.
Я нашел это .

Я понимаю, что это для C ++ , но, кажется, это самое близкое, что я мог найти для того, чего я пытаюсь достичь в пределах.Net Core

В идеальном мире это выглядело бы примерно так

    /// <summary>
    /// Get the file mime type
    /// </summary>
    /// <param name="filePathLocation">file path location</param>
    /// <returns></returns>
    `#if WINDOWS`
    public static string GetMimeType(this string filePathLocation)
    {
        if (filePathLocation.IsValidFilePath())
        {
            string mimeType = "application/unknown";
            string ext = Path.GetExtension(filePathLocation).ToLower();
            Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);

            if (regKey != null && regKey.GetValue("Content Type") != null)
            {
                mimeType = regKey.GetValue("Content Type").ToString();
            }
            return mimeType;
        }
        return null;
    }
`#endif`

Я видел #Define, поэтому я попробовал что-то подобное #define IS_WINDOWS и добавил его в свой классвместе с #if IS_WINDOWS однако я не мог понять, как изменить это значение, если я надеюсь снова и снова использовать статический класс.

1 Ответ

0 голосов
/ 12 сентября 2018

Несмотря на то, что вы могли бы следовать маршруту, включающему #define, это время компиляции, и вы потеряете много многоплатформенного совершенства .Net.Вам также придется жонглировать несколькими конфигурациями, множественными сборками и т. Д.

Где возможно, скрыть зависимое от платформы поведение за независимой от платформы абстракцией и выполнять проверку во время выполнения, используя System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform:

interface IPlatform
{
    void DoSomething();
}

class WindowsImpl : IPlatform
{
    public void DoSomething()
    {
        // Do something on Windows
    }
}

class LinuxImpl : IPlatform
{
    public void DoSomething()
    {
        // Do something on Linux
    }
}

// Somewhere else
var platform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new WindowsImpl() : new LinuxImpl();
platform.DoSomething();

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

Если вам нужно изолировать зависимый от платформы код во время компиляции (возможно, пакет предназначен только для Windows), MEF2 / System.Composition может помочь вам создать инфраструктуру плагинов, где каждыйПлатформа получает свою сборку:

// In Windows.dll class library project
using System.Composition;

[Export(typeof(IPlatform))]
public class WindowsImpl : IPlatform
{
    public void DoSomething()
    {
        //...
    }
}

А затем в вашей основной программе:

using System.Composition.Hosting;

var configuration = new ContainerConfiguration();
var asm = Assembly.LoadFrom(pathToWindowsDll);
configuration.WithAssembly(asm);
var host = configuration.CreateContainer();
var platform = host.GetExports<IPlatform>().FirstOrDefault();
...