确定 .NET 嵌入式资源的名称?

Determining the name of a .NET embedded resource?

假设您在名为 App 的 C# 应用程序中有一个名为 Res 的目录,并且在该目录中您有 icon.png ,大概您将标记为 EmbeddedResource 并在运行时访问它以便为您的应用程序提供图标,代码如下:

        var assembly = System.Reflection.Assembly.GetEntryAssembly();
        var resourceAppIcon = assembly.
            GetManifestResourceStream( "App.Res.icon.png" );

        // Prepare icons
        if ( resourceAppIcon != null ) {
            this.appIconBmp = new Bitmap( resourceAppIcon );
            this.Icon = Icon.FromHandle( this.appIconBmp.GetHicon());
        }

...等等。

这段代码以前是可以运行的,但是自从我改用 JetBrains Rider 后突然停止运行了。尽管资源仍然是嵌入的,但它们的名称已从 namespace.directory.resource_name 更改为 namespace.resource_name。为了访问图标,我现在必须写:

     var resourceAppIcon = assembly.
            GetManifestResourceStream( "App.icon.png" );

这是意料之中的事情吗?只是跟Rider有关吗?也许与 dotnetcore 带来的新时代有关?我一直在努力寻找关于此的文档,但没有任何运气。

已编辑:我尝试使用 CLI 使用 dotnetcore,然后资源名称符合预期。这似乎是 Mono 的问题?

不确定是什么改变了它,但是如果您使用的是带有字符串、文件等的 resx 文件,那么您应该能够让设计器为您生成一个代码文件,其中包含执行正确操作的简单属性,那么您不必在代码中硬编码资源名称,您只需访问生成的 Resources class.

上的属性

如果这不是一个选项,那么我的建议是使用您期望的名称添加一些单元 and/or 集成测试,并确保它们提取正确的数据。

我只是想重播你的问题,但在 dotnetcore(Visual Sutdio 和 JetBrains Rider)中,我可以使用你的“App.Res.icon.png”代码以相同的方式访问嵌入式图像资源,但不能使用“ App.icon.png".

或者我认为您可以尝试类似的方法:

var assembly = System.Reflection.Assembly.GetExecutingAssembly(); // Instead of GetEntryAssembly()
var resourceAppIcon = assembly.GetManifestResourceStream("App.Res.icon.png");

希望对你有所帮助。

嵌入资源的路径可能因用于嵌入资源的属性而异。例如,如果您指定 ManifestResourceName or the LogicalName 属性,路径将与默认路径不同。

此外,如果 EmbeddededResource 使用 DependentUpon 属性 并且它指向 C# class,则资源名称将尝试匹配正在引用的 class 的命名空间,而不是资源所在的文件夹。

当然,如果在项目中也指定了EmbeddedResourceUseDependentUponConvention,则规则会发生变化,在这种情况下,DependentUpon不会受到上述影响。

在我看来,资源名称太脆弱,无法直接使用它们 - 如果有人更改默认命名空间,所有资源名称都会更改,并且没有工具可以自动重构资源名称。因此,我总是通过遍历可用资源名称来解析嵌入式资源,并通过 EndsWith-filter 找到正确的资源。

    var assembly = System.Reflection.Assembly.GetEntryAssembly();
    var resourceName = assembly.GetResourceNames().Single(n => n.EndsWith("icon.png"));
    var resourceAppIcon = assembly.
        GetManifestResourceStream(resourceName);