预处理器:获取操作系统.Net Core

And*_*ewE 4 c# preprocessor-directive .net-core

我正在编写一个我希望在 Windows 和 Linux 上使用的类。

此类中的方法之一是访问Windows 注册表。

我希望实现的是在使用 Linux 计算机时以某种方式禁用此特定方法。

首先,我做了一些研究,看看.Net Core是否有一些东西可以让我检查正在使用哪个操作系统,我发现了这个并且确实可以工作。

当我在访问方法时将其实现到代码中时,我希望禁用访问 Windows 注册表的方法,但是我最接近的方法是使用 switch 语句,如下所示

switch (OS)
{
    case OSX:
    return;

    case LINUX:
    return
}
Run Code Online (Sandbox Code Playgroud)

如果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`
Run Code Online (Sandbox Code Playgroud)

我确实看到了#Define,所以我尝试了类似的方法#define IS_WINDOWS并将其添加到我的类中#if IS_WINDOWS ,但是,如果我希望一遍又一遍地重用静态类,我不知道如何更改该值。

Jak*_*ake 5

虽然您可以采用涉及 .Net 的路线#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();
Run Code Online (Sandbox Code Playgroud)

这对于包括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()
    {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的主程序中:

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();
Run Code Online (Sandbox Code Playgroud)