您可以在ResourceManager 上创建扩展方法。
public static class ResourceExtensions
{
public static MemoryStream GetMemoryStream(this ResourceManager resourceManager, String name) {
object resource = resourceManager.GetObject(name);
if (resource is byte[]) {
return new MemoryStream((byte[])resource);
}
else {
throw new System.InvalidCastException("The specified resource is not a binary resource.");
}
}
}
打电话
ResourceManager resourceManager = Properties.Resources.ResourceManager;
MemoryStream stream = resourceManager.GetMemoryStream("binaryResource");
不过,这似乎也一样。
MemoryStream stream = new MemoryStream(Properties.Resources.SomeBinaryResource);
我不确定我是否会修改资源文件,因为它们很容易更改,而且我确信在某些情况下 Visual Studio 会覆盖更改。
根据您的担忧,问题在于这会将数据的副本创建到内存中,从而产生内存占用。对于寿命很短的轻量级资源,这不是问题,但它可能是一个大问题。
答案很简短:使用ResourceManager 无法避免内存占用。问题是ResourceManager.GetObject(String) 和ResourceManager.GetStream(String) 都创建了数据的副本。尽管GetStream(String) 返回一个UnmanagedMemoryStream,它实际上在内部调用GetObject(String),并且仍然创建了一个副本。如果您调试您的应用程序并分析内存,您将看到内存仍在分配中。
我尝试了多种方法来解决这个问题,方法是在 unsafe 上下文中使用指针,然后进行反射,但没有任何效果。 ResourceManager 没有那么灵活或优化。
不过,我能够找到解决方案,但它需要您使用 Embedded Resources。除了将资源文件的构建操作设置为Embedded Resource 以获取Build Action 之外,这不会改变任何内容。使用它,您可以使用反射来创建不创建数据副本的UnmanagedMemoryStream。
private UnmanagedMemoryStream GetUnmanagedMemoryStream(String embeddedResourceName) {
Assembly assembly = Assembly.GetExecutingAssembly();
string[] resourceNames = assembly.GetManifestResourceNames();
string resourceName = resourceNames.SingleOrDefault(resource => resource.EndsWith(embeddedResourceName, StringComparison.InvariantCultureIgnoreCase));
if (resourceName != null) {
return (UnmanagedMemoryStream)assembly.GetManifestResourceStream(resourceName);
}
else {
throw new System.ArgumentException("The specified embedded resource could not be found.", "embeddedResourceName");
}
}
我没有对此进行广泛的测试,但它确实有效。我的测试数据是一个 17 兆字节的小文件。我的测试应用程序的工作集内存从大约 50 兆字节开始,在将资源检索到流中后,它不会改变。当使用ResourceManager 时,它会立即将工作集增加资源的大小。
您可能需要换出对 EndsWith 的调用以检查清单中的正确资源名称,因为资源名称与直接通过 ResourceManager 访问它略有不同。
我真的很失望,我无法使用现有的 ResourceManager 找到解决方案,但它不够灵活。
编辑我写了in-depth blog article here about this subject。