Preprocessor : Get Operating System .Net Core

北城以北 提交于 2021-02-09 15:23:22

问题


I'm writing a class that I wish to use on both Windows & Linux.

One of the methods that is in this class is accessing the Windows Registry

What I'm hoping to achieve is to somehow disable this particular method from being used when using a Linux machine.

First of all I did some research to see if there was something for .Net Core that would allow me to check which operating system is in use, I found this and sure enough that works.

When I implemented it into my code when accessing a method, I was hoping to disable the method that's accessing the windows registry, however the closest I could get to this was using a switch statement, something like this

switch (OS)
{
    case OSX:
    return;

    case LINUX:
    return
}

To return if the operating system was not supported, this worked, however I then thought disabling it from being accessed all together would be much better rather than throwing an error for an operating system thats not supported for that particular method

I then went on to look at preprocessor directives thinking that if I'm able to detect and disable parts of code depending the frameworks etc, maybe I could use something like this to disable parts of code depending on the operating system that way they could never be called even when trying to access the method

I went on from there to see if I could disable parts of code using preprocessor directives.
I found this.

I understand that it is for C++ however it seems to be the closest I could find for what I'm trying to achieve within .Net Core

In a perfect world, it would look something like this

    /// <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`

I did see #Define so I tried something like this #define IS_WINDOWS and added it to my class along with #if IS_WINDOWS however, I couldn't see how to change that value if I'm hoping to just reuse the static class over and over.


回答1:


While you could pursue a route involving #define, it's compile-time and you'll loose a lot of .Net's multi-platform goodness. You'll also have to juggle multiple configurations, multiple builds, etc.

Where possible, hide the platform-dependent behavior behind a platform-independent abstraction and do the check at runtime using 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();

This works well for many things including PInvoke. You will be able to use the same binaries on either platform, and it will be easier to add OSX later.

If you need to isolate the platform-dependent code at compile-time (perhaps a package is Windows-only), MEF2/System.Composition can help you make a plugin framework where each platform gets its own assembly:

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

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

And then in your main program:

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();


来源:https://stackoverflow.com/questions/52295448/preprocessor-get-operating-system-net-core

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!