企业库验证应用程序阻止和国际化

oll*_*SFT 5 .net globalization enterprise-library localization validation-application-bl

脚本

.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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如代码注释中所述,当您在EnterpriseLibrary验证程序上调用Validate()时,验证消息已经本地化为法语,您没有机会将它们写入例如英语日志文件.

在我们的应用程序的其他方面,我们使用一个消息类来封装资源ID和参数,直到我们确定我们想要使用哪种文化来解析实际的字符串值.您可以将其称为延迟资源解析.

有关如何将相似机制引入企业库验证块的任何想法?目前为止的想法:

  • 临时切换CurrentCulture(我不喜欢它,它只解决了一半的问题)
  • 修补企业库验证块(我也不喜欢它)

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

Ran*_*ica 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>
Run Code Online (Sandbox Code Playgroud)

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

您可能还需要考虑为消息的目标受众创建多个资源文件。即,一种用于用户消息的资源,一种用于技术消息的资源。因此,您可以为用户消息提供 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"));
Run Code Online (Sandbox Code Playgroud)


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