如何从 .NET Standard 2.0 和 UWP 获取进程内存?

How to get process memory from both .NET Standard 2.0 and UWP?

我正在开发小型 .NET Standard 2.0 logging library,但我无法找到一种方法来可靠地获取当前进程在所有平台上使用的内存,尤其是在 UWP 上。

现在我正在使用此代码 (.NET Standard 2.0):

long memory = Process.GetCurrentProcess().PrivateMemorySize64;

工作正常,但是 在 UWP 上抛出一个很好的 PlatformNotSupportedException 异常(实际上,那只是在 DEBUG 模式下,而在 RELEASE 中直接抛出一个 TypeLoadException加上一些其他P/Invoke出于某种原因的异常)。

这里的问题是UWP显然不支持API,我应该使用:

long memory = (long)MemoryManager.AppMemoryUsage;

问题是 MemoryManager 是 UWP-only API,它不存在于 .NET Standard 2.0 中。现在,想到的第一个解决方法是在库中公开一个设置,让用户手动设置一个自定义 Func<long> 委托来检索当前内存使用情况,这样如果它知道默认方法将不起作用在当前平台上,可以覆盖它。

尽管这似乎是个糟糕的把戏,但我希望在库中保留所有内容。所以我的问题是:

Is there a way to reliably retrieve the current process/app usage across any platform that supports .NET Standard 2.0 libraries?

谢谢!

我认为您可以使用之前用于便携式 Class 库的相同技巧 - Bait and Switch. It is still compatible with .NET Standard 2.0。这样您就可以为 UWP 创建一个特定的实现,否则回退到标准实现。

可能有点脏,但下面的方法可以工作(可能会添加一些更好的错误处理等):

public static long GetProcessMemory()
{
    try
    {
        return Process.GetCurrentProcess().PrivateMemorySize64;
    }
    catch
    {           
        var type = Type.GetType("Windows.System.MemoryManager, Windows, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime");
        return Convert.ToInt64(type.GetProperty("AppMemoryUsage", BindingFlags.Public | BindingFlags.Static).GetValue(null, null));
    }
}

我使用反射来解决以下事实:MemoryManager 在编译时不适用于 .NET Standard,但适用于 UWP 运行时。这样,同一个程序集将适用于两个运行时。
但总的来说,我更喜欢像 Martin 建议的那样在每个运行时生成一个合适的程序集的方法。