2

我想将ASP.NET MVC客户端验证与NHibernate.Validator集成在一起,唯一的问题是我无法将非插值消息转换为一个人可读的。我认为这将是一件容易的事情,但事实证明这是客户端验证中最难的部分。主要的问题是,因为它不是服务器端,我实际上只需要正在使用的验证属性,而我实际上并没有实例或其他任何东西。如何在NHibernate.Validator中插入消息

下面是我一直在努力已经一些摘录:

// Get the the default Message Interpolator from the Engine 
IMessageInterpolator interp = _engine.Interpolator; 
if (interp == null) 
{ 
    // It is null?? Oh, try to create a new one 
    interp = new NHibernate.Validator.Interpolator.DefaultMessageInterpolator(); 
} 

// We need an instance of the object that needs to be validated, se we have to create one 
object instance = Activator.CreateInstance(Metadata.ContainerType); 

// we enumerate all attributes of the property. For example we have found a PatternAttribute 
var a = attr as PatternAttribute; 

// it seems that the default message interpolator doesn't work, unless initialized 
if (interp is NHibernate.Validator.Interpolator.DefaultMessageInterpolator) 
{ 
    (interp as NHibernate.Validator.Interpolator.DefaultMessageInterpolator).Initialize(a); 
} 

// but even after it is initialized the following will throw a NullReferenceException, although all of the parameters are specified, and they are not null (except for the properties of the instance, which are all null, but this can't be changed) 
var message = interp.Interpolate(new InterpolationInfo(Metadata.ContainerType, instance, PropertyName, a, interp, a.Message)); 

我知道上面是一个看似简单的问题相当复杂的代码,但我仍然坚持没有解决之道。有没有办法从NHValidator中获取内插字符串?

回答

2

好的,所以我知道这是一个古老的问题,但当我尝试做同样的事情时,我偶然发现了这一点,它帮助我开始 - 所以我想我会提供一个答案。

我认为问题中的代码在正确的轨道上,但有几个问题。内插器没有完全使用ResourceManagerCulture的详细信息初始化,并且它似乎没有考虑到每个验证属性只能有一个DefaultMessageInterpolator这一事实。此外,您不需要您正在验证的对象的实例来获取内插消息。

在问题的代码中,如果要使用属性值初始化插补器,还需要初始化插值器,并使用要使用的ResourceManager的详细信息。

这可以通过使用重载Initialize方法上做DefaultMessageInterpolator它具有以下特征:

public void Initialize(ResourceManager messageBundle, 
          ResourceManager defaultMessageBundle, 
          CultureInfo culture) 

第一个参数是如果你想使用的错误消息您自己的资源文件中的用户定义的ResourceManager ,你可以通过一个空,如果你只是想使用默认ResouceManager,第二个参数是默认的ResourceManager - 你可以通过

new ResourceManager( 
     NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource, 
     Assembly.GetExecutingAssembly()); 

这一点,最后一个参数是文化(NHibernate.Validator自带的资源文件带有几种语言的验证信息) - 如果你通过一个空值进入它,它将只使用CultureInfo.CurrentCulture

最后,每个属性只能有一个DefaultMessageInterpolator,所以你需要为每个验证属性创建一个新的DefaultMessageInterpolator。你可以利用DefaultMessageInterpolatorAggregator来处理这个问题,或者只是推出你自己的。

我希望这可以帮助别人。

1

感谢您的帮助 - 如果可以的话,我会赞成。我只想补充一点,除了Stank说明的DefaultMessageInterpolator上的第一个Initialize调用外,我还必须做第二个不同的Initialize调用才能完全初始化它(我只使用第一个调用获得了一些Null引用异常)。我的代码如下:

string interpolatedMessage = ""; 
DefaultMessageInterpolator interpolator = new DefaultMessageInterpolator(); 

interpolator.Initialize(null, 
    new ResourceManager(
     NHibernate.Validator.Cfg.Environment.BaseNameOfMessageResource, 
     Assembly.Load("NHibernate.Validator")), 
     CultureInfo.CurrentCulture); 

interpolator.Initialize(attribute as Attribute); 

if (attribute is IValidator && attribute is IRuleArgs) 
{ 
    IValidator validator = attribute as IValidator; 
    IRuleArgs ruleArgs = attribute as IRuleArgs; 

    InterpolationInfo interpolationInfo = new InterpolationInfo(
     validatableType, 
     null, 
     propertyName, 
     validator, 
     interpolator, 
     ruleArgs.Message); 

    interpolatedMessage = interpolator.Interpolate(interpolationInfo); 
} 
相关问题