如何继承资源文件(resx)

发布于 2024-11-26 21:28:37 字数 846 浏览 2 评论 0原文

假设您正在开发一个由数百个程序集组成的 .Net 4.0 项目,每个程序集都有自己的用于本地化的资源文件 (.resx)。通过使用 ResXFileCodeGenerator 自动生成的类(创建“ResourceFile.Designer.cs”文件)从 C# 访问本地化字符串: string test = ResourceFile.TestString;

每个程序集都有特定的本地化字符串但有一些字符串对于所有程序集都是通用的。您告诉自己,最好将这些“通用字符串”放在“父”资源文件中,如果“本地”资源文件中的资源键不可用,则代码将回退到该字符串上。然后你会说“嘿!继承在这里可以发挥作用。”事实上,在自动生成的设计器文件中执行类似的操作确实有效: 内部类ResourceFile:ParentResourceFile 也就是说,未在 ResourceFile 中定义但在 ParentResourceFile 中定义的字符串仍然可以使用 ResourceFile.StringInParentFile 进行访问。

但是设计器文件头中的某些内容让您感到困扰:“对此文件的更改可能会导致不正确的行为,并且如果重新生成代码,则会丢失”此外,您知道在自动生成的设计器文件是不受欢迎的。所以你来到这里,你会问:

  • ResXFileCodeGenerator什么时候生成/重新生成设计器 班级?
  • 有没有办法关闭自动生成?
  • 我们会不会有 放弃 ResXFileCodeGenerator 的优点并实现我们的 自己处理ResourceManager?

然后你说“谢谢”。

Imagine you're working on a .Net 4.0 project that is made up of hundreds of assemblies, each having its own resource file (.resx) for localization. The localized strings are accessed from C# through classes auto-generated with ResXFileCodeGenerator (which creates a "ResourceFile.Designer.cs" file): string test = ResourceFile.TestString;

Each assembly has localized strings which are particular to it, but there are strings which are common to all assemblies. You tell yourself that it would be nice to have those "common strings" in a "parent" resource file, on which the code would fall back if the resource key is not available in the "local" resource file. You then say "Hey! inheritance could work here." And indeed, doing something like this in the auto-generated designer file does work:
internal class ResourceFile : ParentResourceFile
That is, strings not defined in ResourceFile, but defined in ParentResourceFile, can still be accessed with ResourceFile.StringInParentFile.

But something in the designer file's header troubles you: "Changes to this file may cause incorrect behavior and will be lost if the code is regenerated." Plus you know playing in the auto-generated designer files is frowned upon. So you come here, and you ask:

  • When does ResXFileCodeGenerator generate/regenerate the designer
    class?
  • Is there a way to turn off that auto-generation?
  • Will we have
    to forego the advantages of ResXFileCodeGenerator and implement our
    own handling of ResourceManager?

And you say "thank you".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

李不 2024-12-03 21:28:37

在研究这个问题一段时间后,我找到了一个解决方法:不在资源文件本身上继承,而是在需要访问“父”资源的类上继承。

您只需要有一个基类,其项目包含一个“主”资源文件,并将该资源文件的 CustomTool 属性设置为 PublicResXFileCodeGenerator (“Public”部分很重要,因为它将创建一个 public 类,而不是内部 类)。一个限制是 PublicResXFileCodeGenerator 只能从 VS2008 开始使用(这篇 CodeProject 文章 可能会有帮助)。

然后,在需要访问“主”资源的类中,只需从基类继承并访问资源,如下所示:

public class ChildClass : BaseClass
{
    string test = BaseClass.BaseResourceFile.TestString; // a common resource
    string localResource = ResourceFile.OtherString;     // a local resource
}

此解决方案的一个缺点是您必须显式引用 BaseResourceFile 才能访问其中定义的资源;没有像在资源类之间直接完成继承那样回退到父类。

对于后代,我将回答我自己的问题:

  • ResXFileCodeGenerator 何时生成/重新生成设计器
    类?

    每当添加/删除/修改资源时。

  • 有办法关闭自动生成吗?

    没有。无论如何,没有自动生成功能的“代码生成器”工具将毫无用处,您不觉得吗?

  • 我们是否必须放弃 ResXFileCodeGenerator 的优势并实现我们的
    自己处理ResourceManager?

    不,请参阅上面的答案。

我们还考虑使用“链接”文件(从“添加现有项目”对话框,使用“添加为链接”选项)实现一种解决方案,其中一个父资源文件将链接到我们的所有程序集,但由于我们的程序集已经继承自一个基类,走继承的路似乎要好得多。

我不太愿意接受自己的答案,所以如果有人提出更好的解决方案或对我的解决方案进行改进,我很乐意接受。也就是说,如果有人关心的话。

After investigating the issue for a while, I've settled for a workaround: do inheritance not on the resource files themselves, but on the classes that need to access the "parent" resources.

You only need to have a base class whose project includes a "master" resource file, and set that resource file's CustomTool property to PublicResXFileCodeGenerator (the "Public" part is important as it will create a public class, as opposed to an internal one). One restriction is that PublicResXFileCodeGenerator is only available starting with VS2008 (this CodeProject article could otherwise be helpful).

Then, in classes which need to access the "master" resources, simply inherit from the base class and access the resources like this:

public class ChildClass : BaseClass
{
    string test = BaseClass.BaseResourceFile.TestString; // a common resource
    string localResource = ResourceFile.OtherString;     // a local resource
}

One disadvantage with this solution is that you have to explicitly reference the BaseResourceFile to access resources defined there; there's no fallback to the parent class like there would be if inheritance was done directly between the Resource classes.

And for posterity, I'll answer my own questions:

  • When does ResXFileCodeGenerator generate/regenerate the designer
    class?

    Whenever a resource is added/removed/modified.

  • Is there a way to turn off that auto-generation?

    No. And anyway, a "code generator" tool without auto-generation would be pretty useless, don't you think?

  • Will we have to forego the advantages of ResXFileCodeGenerator and implement our
    own handling of ResourceManager?

    No, see above answer.

We also considered implementing a solution using "linked" files (from the "Add existing item" dialog, using the "Add as link" option) where one parent resource file would be linked to all our assemblies, but since our assemblies already inherit from a base class, it seemed much better to go the inheritance way.

I don't really feel comfortable accepting my own answer, so if anyone comes up with a better solution or improvements on my solution, I'd gladly accept that. That is, if anyone cares at all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文