5

设想

.NET/WPF 桌面应用程序应该本地化(或 MS 术语globalized)到与英语不同的语言。也就是说,需要完全采用 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(我不喜欢这样,它只解决了一半的问题)
  • 修补企业库验证块(我也不喜欢那样)

感谢您的帮助和分享想法!

4

1 回答 1

4

当我们需要延迟资源解析时,我们放弃了使用MessageTemplateResourceName,而是将我们的资源 id 作为MessageTemplate属性。然后我们稍后使用该 id 使用当前文化查找资源字符串值。

我们标准化了 id 的命名约定,如下所示:RULESET_RULESETQUALIFIER_OPERATION_OBJECT_PROPERTY_VALIDATIONTYPE. 例如RULESET_BMW_INSERT_CAR_YEAR_RANGERULESET_BMW_UPDATE_CAR_COLOR_LENGTH等。

在 VAB 配置中,这看起来像:

<property name="Color">
   <validator lowerBound="0" lowerBoundType="Ignore" upperBound="50"
    upperBoundType="Inclusive" negated="false" messageTemplate="RULESET_BMW_INSERT_CAR_COLOR_LENGTH"
    messageTemplateResourceName="" messageTemplateResourceType=""
    tag="" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    name="String Length Validator" />
                    </property>

主要的缺点是您无法轻松使用消息模板标记来使消息略微动态化。这可以完成,但令牌值必须存储在某处(例如您的消息类),以便稍后在评估消息字符串时可以替换它们。

您可能还需要考虑为消息所针对的每个受众创建多个资源文件。也就是说,一种资源用于用户消息,一种资源用于技术消息。因此,您可以为用户消息提供 UserMessages.resources、UserMessages.fr-BE.resources。然后在另一个资源文件中复制具有不同日志消息的 id (LogMessages.resources)。这样您就可以获得日志消息的其他技术信息。不过,这可能有点矫枉过正。

然后我们使用以下方法访问字符串值ResourceManager

ResourceManager userResourceManager = 
    new ResourceManager("UserMessages", Assembly.GetExecutingAssembly());

string userMessage = userResourceManager.GetString(resourceId);

ResourceManager logResourceManager = 
    new ResourceManager("LogMessages", Assembly.GetExecutingAssembly());

// Can also try to use InvariantCulture instead of "en"
string messageToLog = logResourceManager.GetString(resourceId,  new CultureInfo("en"));
//alternative to ensure you get the english user message value:
//    string messageToLog = userResourceManager.GetString(resourceId,  new CultureInfo("en"));


您可以将其抽象为辅助类或将其添加到您的消息类中。您可能还需要构建一些代码来提取 ValidationResults 并使用您需要的信息创建消息类。

于 2010-08-08T06:25:39.483 回答