企业库验证应用程序块和国际化
场景
.NET/WPF 桌面应用程序应本地化(或用 MS 术语全球化)为与英语不同的语言。也就是说,UI 需要完全采用(标签、图标……)。
然而,日志文件条目、审计跟踪条目和应用程序的其他输出应保留为英语,以便英语服务/支持人员对其进行审查。他们不会说法语或中文。
该应用程序依赖 RESX 文件来完成本地化。
企业库验证块用于验证对象模型上的业务规则。
现在假设有一个服务在执行实际业务逻辑之前验证其给定的对象模型参数。在某些情况下,它会收到无效的对象模型参数,但会尽力继续执行。然而,无效对象模型数据的提供应记录在审计跟踪和日志文件中。
使用验证块的服务示例。
public class Service : IService
{
public void MyMethod(MyObjectModelObject obj)
{
Validator validator = ValidationFactory.CreateValidator(typeof(MyObjectModelObject));
ValidationResults results = validator.Validate(this);
// !!! The messages in the validation results are now already localized to CurrentCulture.
// ... build a log message: msg
if (results.Count > 0)
{
Logger.Log(msg);
}
}
}
如代码注释中所述,当您在 EnterpriseLibrary 验证器上调用 Validate() 时,验证消息已本地化为法语,并且您没有机会将它们写入例如英语日志文件。
在应用程序的其他区域中,我们使用封装资源 ID 和参数的消息类,直到我们确定要使用哪种区域性来解析实际的字符串值。您可以将其称为延迟资源解析。
有什么想法如何向企业库验证块引入类似的机制吗?到目前为止的想法:
- 暂时切换 CurrentCulture(我不喜欢这样,它只解决了一半问题)
- 修补企业库验证块(我也不喜欢那样)
感谢您的帮助和分享的想法!
Scenario
A .NET/WPF desktop application should be localized (or in MS terms globalized) to a different language than English. That is, the UI needs to be adopted completely (labels, icons, ...).
Log file entries, audit trail entries, and other outputs of the application, however, should remain in English to allow the English-speaking service/support personnel reviewing it. They do not speak French or Chinese.
The application relies on RESX files for accomplishing the localization.
The Enterprise Library Validation Block is used for the validation of business rules on the object model.
Now suppose there is a service that validates its given object model arguments prior to executing the real business logic. Under some circumstances it receives invalid object model arguments but continues the execution with best effort. The provision of invalid object model data, however, should be logged in the audit trail and in the log file.
Example of a service using the validation block.
public class Service : IService
{
public void MyMethod(MyObjectModelObject obj)
{
Validator validator = ValidationFactory.CreateValidator(typeof(MyObjectModelObject));
ValidationResults results = validator.Validate(this);
// !!! The messages in the validation results are now already localized to CurrentCulture.
// ... build a log message: msg
if (results.Count > 0)
{
Logger.Log(msg);
}
}
}
As stated in the code comment, when you've called Validate() on the EnterpriseLibrary validator, the validation messages are already localized to French and you have no chance to write them to a e.g. English log file.
In other areas of our application we use a message class that encapsulates the resource id and parameters until we are certain which culture we want to use the resolve the actual string value. You could call it a deferred resource resolution.
Any ideas how to introduce a similar mechanism to the Enterprise Library Validation block? Ideas so far:
- Switching the CurrentCulture temporarily (I don't like that and it solves only half the problem)
- Patch the Enterprise Library Validation Block (I don't like that, too)
Thanks for your help and shared ideas!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当我们需要延迟资源解析时,我们放弃使用
MessageTemplateResourceName
,而是将资源 ID 作为MessageTemplate
属性。然后,我们稍后使用该 id 来使用当前区域性查找资源字符串值。我们标准化了 id 的命名约定,如下所示:
RULESET_RULESETQUALIFIER_OPERATION_OBJECT_PROPERTY_VALIDATIONTYPE
。例如RULESET_BMW_INSERT_CAR_YEAR_RANGE
或RULESET_BMW_UPDATE_CAR_COLOR_LENGTH
等。在 VAB 配置中,这看起来像这样:
主要缺点是您无法轻松使用消息模板令牌来制作消息稍微动态。这可以完成,但令牌值必须存储在某个地方(例如消息类),以便稍后在评估消息字符串时可以替换它们。
您可能还需要考虑为消息的目标受众创建多个资源文件。即,一种用于用户消息的资源,一种用于技术消息的资源。因此,您可以为用户消息提供 UserMessages.resources、UserMessages.fr-BE.resources。然后在另一个资源文件中复制具有不同消息的 id 以进行日志记录 (LogMessages.resources)。这样您就可以获得日志消息的附加技术信息。但这可能有点过分了。
然后,我们使用
ResourceManager
访问字符串值:您可以将其抽象为辅助类或将其添加到消息类中。您可能还需要构建一些代码来提取 ValidationResults 并使用您需要的信息创建消息类。
When we had a requirement for deferred resource resolution we abandoned using the
MessageTemplateResourceName
and instead put our resource id as theMessageTemplate
property. We then use that id later to look up the resource string value using the current culture.We standardized the naming convention for the id something like this:
RULESET_RULESETQUALIFIER_OPERATION_OBJECT_PROPERTY_VALIDATIONTYPE
. e.g.RULESET_BMW_INSERT_CAR_YEAR_RANGE
orRULESET_BMW_UPDATE_CAR_COLOR_LENGTH
etc.In the VAB configuration this would look something like:
The major downside is that you lose the ability to easily use the message template tokens to make the message slightly dynamic. This could be accomplished but the token values would have to be stored somewhere (e.g. you message class) so that they could be substituted later when the message string is evaluated.
You may also want to consider creating multiple resource files for each of the audiences the messages are targeted for. That is, one resource for user messages and one for technical messages. So you could have UserMessages.resources, UserMessages.fr-BE.resources for the user messages. Then in another resource file duplicate the ids with different messages for logging (LogMessages.resources). That way you could have additional technical information for the log message. This might be overkill though.
We then access the string values using the
ResourceManager
:You could abstract this away into a helper class or add it to your message class. You may also have to build some code to extract the ValidationResults and create message classes with the information you require.