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); 
} 
相關問題