EntLib 验证:无需资源的本地化 - 从配置进行验证

发布于 2024-10-11 05:24:08 字数 548 浏览 2 评论 0原文

我想使用我自己的本地化实现,而不是框架提供的默认资源文件系统。我还需要在配置文件中配置验证器。

我的问题是,在实例化 ConfigurationValidatorFactory 后,我不知道如何访问 Validator 对象来更改其消息模板。我可以为我的对象创建一个验证器,如下所示:

var cfgSrc = new FileConfigurationSource("Validations.xml");
var factory = ConfigurationValidatorFactory.FromConfigurationSource(cfgSrc);
Validator val = factory.CreateValidator<MyObj>();

,但是上面的“val”是 GenericValidatorWrapper 类型,并且没有属性来访问“真正的验证器”实例。

验证后,我可以看到真正的验证器实例,但更改其模板文本为时已晚。最终消息(包含限制值)已创建,更改模板不会重新创建消息。

有什么建议吗?

企业库版本是5。

I would like to use my own localization implementation instead of the default resource file system the framework provides. I need also to configure the validators in a configuration file.

My problem is that I don't know how to access the Validator objects to change their message templates after I have instantiated the ConfigurationValidatorFactory. I can create a validator for my object like this:

var cfgSrc = new FileConfigurationSource("Validations.xml");
var factory = ConfigurationValidatorFactory.FromConfigurationSource(cfgSrc);
Validator val = factory.CreateValidator<MyObj>();

, but 'val' above is then of type GenericValidatorWrapper and has no properties to access the 'true validator' instances.

After validation I can see the true Validator instances, but then it is too late to change their template text. The final message (containing the limit values) has then already been created and changing the template won't re-create the message.

Any suggestions?

Enterprise Library version is 5.

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

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

发布评论

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

评论(1

人疚 2024-10-18 05:24:08

您也许可以使用反射来修改您感兴趣的验证器属性。但这确实很混乱且笨拙。

如果您在验证后只是替换验证结果上的消息文本会怎么样?

配置文件中的消息可以是占位符(例如NAME_INVALID_LENGTH),您可以将其替换为实际文本。

var cfgSrc = new FileConfigurationSource("Validations.xml");
var factory = ConfigurationValidatorFactory.FromConfigurationSource(cfgSrc);
Validator val = factory.CreateValidator<MyObj>();

MyObj myObj = new MyObj();
myObj.Name = "Swiper McFoxy";

ValidationResults results = new ValidationResults();

foreach (ValidationResult result in val.Validate(myObj))
{
    results.AddResult(
        new ValidationResult(
            GetMessage<MyObj>(result.Message, new CultureInfo("en")),
            result.Target,
            result.Key,
            result.Tag,
            result.Validator,
            result.NestedValidationResults));
}

更新

好的,如果您需要模板文本,您可以通过反射进行研究,但这看起来仍然很混乱。

考虑到您的要求(配置文件、维护模板),我可能会做的是创建多个配置文件,每个文件都包含您想要的模板文本。

这有点维护噩梦,所以我将这个想法改进为:

  1. 创建我的配置文件Validations.xml,而不是将模板化文本放入其中,而是为每条消息使用唯一的占位符(例如 NAME_INVALID_LENGTH,但更独特)。

  2. 然后我会编写一小段代码/工具,对于您支持的每个区域设置,将唯一的占位符替换为特定于区域设置的模板文本。并将生成的文件复制到 OutDir 下的区域设置特定文件夹(例如 bin\debug\en-US\Validations.xml)。这类似于 .NET 部署卫星程序集的方式,因此并不是那么困难。

  3. 作为构建后步骤运行上面的工具。该工具可以标记它找不到的占位符,以便在构建过程中报告它。这应该有助于保持占位符和模板文本同步。

  4. 修改您的代码以使用特定于区域设置的配置文件:

    CultureInfo 文化 = new CultureInfo("en-us");
    var cfgSrc = new FileConfigurationSource(culture.Name + @"\Validations.xml");
    var 工厂 = ConfigurationValidatorFactory.FromConfigurationSource(cfgSrc);
    Validator val = factory.CreateValidator();
    

    您可以抽象辅助方法背后的区域性特定代码,以便更容易阅读和维护。例如 GetValidationConfigurationSource(culture)

You might be able to use reflection to modify the validator properties that you are interested in. But that is really messy and Kludgy.

What if you simply replaced the message text on the validation results after validation?

The message in the configuration file could be a place holder (e.g. NAME_INVALID_LENGTH) and you could replace that with your actual text.

var cfgSrc = new FileConfigurationSource("Validations.xml");
var factory = ConfigurationValidatorFactory.FromConfigurationSource(cfgSrc);
Validator val = factory.CreateValidator<MyObj>();

MyObj myObj = new MyObj();
myObj.Name = "Swiper McFoxy";

ValidationResults results = new ValidationResults();

foreach (ValidationResult result in val.Validate(myObj))
{
    results.AddResult(
        new ValidationResult(
            GetMessage<MyObj>(result.Message, new CultureInfo("en")),
            result.Target,
            result.Key,
            result.Tag,
            result.Validator,
            result.NestedValidationResults));
}

Update

OK, if you need the template text you can investigate poking around via reflection but that still looks really messy.

Given your requirements (configuration file, maintain templates) what I would probably do would be to create multiple configuration files each with the template text you want.

That's a bit of a maintenance nightmare so I would refine that idea to:

  1. Create my configuration file Validations.xml and instead of putting my templated text in I would use a unique placeholder for each message (e.g. NAME_INVALID_LENGTH but even more unique-ish).

  2. Then I would write a small piece of code/tool that would, for every locale you are supporting, replace the unique placeholder with the locale specific templated text. And copy the resultant file to a locale specific folder under the OutDir (e.g. bin\debug\en-US\Validations.xml). This is similar to how .NET deploys satellite assemblies so it is not that far a stretch.

  3. Run the tool above as a post-build step. The tool can flag placeholders that it can't find so that it gets reported during the build. This should help keep the placeholders and the template text in sync.

  4. Modify your code to use the locale specific configuration file:

    CultureInfo culture = new CultureInfo("en-us");
    var cfgSrc = new FileConfigurationSource(culture.Name + @"\Validations.xml");
    var factory = ConfigurationValidatorFactory.FromConfigurationSource(cfgSrc);
    Validator val = factory.CreateValidator<MyObj>();
    

    You can abstract the culture specific code behind a helper method so that it's easier to read and maintain. e.g. GetValidationConfigurationSource(culture).

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