我正在编写一个我希望在Windows和Linux上使用的类。 本课程中的一种方法是访问Windows Registry 我希望实现的是以某种方式禁用在使用Linux机器时使用此特定方法。 首先,我做了一些研究,看看是否有一些.Net Core的东西可以让我检查哪个操作系统正在使用,我发现this并且确定有效。 当我在访问方法时将其实现到我的代码中时,我希望禁用访问Windows注册表的方法,但是我能得到的最接近的是使用switch语句,类似这样的
switch (OS)
{
case OSX:
return;
case LINUX:
return
}
对于return
,如果不支持操作系统,这是有效的,但是我认为禁止它一起访问会更好,而不是为不支持该特定方法的操作系统抛出错误
然后我继续看看preprocessor directives认为如果我能够根据框架等检测和禁用部分代码,也许我可以使用这样的东西来禁用部分代码,具体取决于操作系统,他们永远不会这样做即使在尝试访问该方法时也会调用
我继续从那里看看我是否可以使用preprocessor directives
禁用部分代码。
我找到了this。
我明白这是为了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
一起添加到我的班级但是,如果我希望一次又一次地重复使用静态类,我无法看到如何更改该值。
虽然你可以追求一个涉及#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();