【问题标题】:Determining the name of a .NET embedded resource?确定 .NET 嵌入式资源的名称?
【发布时间】:2020-06-30 11:00:28
【问题描述】:

假设您在名为 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 的问题?

【问题讨论】:

  • 您提到了 Rider 和 .NET Core。这会在 Visual Studio 中重现吗?还是您在切换到 Rider 时也碰巧升级到了 .NET Core?
  • 您的 CSProj 包括资源的情况如何?
  • FWIW,可以在 Visual Studio 中正常工作,但请注意,在 Visual Studio 中,项目中有默认命名空间的概念,通常是项目名称,但可以更改。如果改变了,资源路径也会改变。
  • @zastrowm,我不知道,我不能使用 Visual Studio,因为我不使用 Windows。我使用的不是 dotnetcore,而是 .NET 框架。
  • @zastrowm,我让项目使用默认的嵌入资源信息: ...我知道我可以在里面使用 LogicalName 节点,这可以解决问题,但我想在此之前了解原因。

标签: c# .net mono embedded-resource rider


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我只是想重播您的问题,但在使用 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");
    

    希望对你有所帮助。

    【讨论】:

    • 也许是网络框架发生了变化,而不是 Mono。我尝试了 GetExecutingAssembly 无济于事。
    • 是的,也许这是一个与单声道有关的问题,毕竟。请检查问题中的编辑。
    • 是的,我重播了,问题似乎出在单声道
    【解决方案3】:

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

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

    【讨论】:

    • 如何将 resx 文件与嵌入式资源相关联?你能详细说明一下吗?
    • resx 文件允许您像嵌入资源一样将字符串、文件等放入二进制文件中,但还提供设计器支持,以便您可以访问 Resources.[PropertyName] 以获取嵌入式资源而不关心它的内部名称是什么。他们还提供本地化支持。
    【解决方案4】:

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

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

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

    【讨论】:

    • 我知道我可以使用 LogicalName,但在此之前,至少对我而言,默认值为 root_namespace.directory.resource,并且想知道为什么会发生这种变化。我不知道 EmbeddedResourceUseDependentUponConvention,但我的项目中没有使用这个,也没有使用 DependentUpon。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-10
    • 2016-12-13
    • 2011-10-30
    • 2017-11-18
    • 2011-10-22
    • 1970-01-01
    相关资源
    最近更新 更多