簡體   English   中英

IViewLocalizer 內部 string.Format 並且沒有參數傳遞到自定義 IStringLocalizer

[英]IViewLocalizer internally string.Format and no params are passed into custom IStringLocalizer

想象一下這個字符串: Welcome, {0}. Your age is {1} Welcome, {0}. Your age is {1} 如果有人執行@Localizer["welcome", "Timmy"]頁面將無法呈現,因為它需要 2 個參數而不是 1 個。

我從IStringLocalizer繼承的自定義實現具有以下代碼:

public LocalizedString this[string name] => this[name, new object[0]];

public LocalizedString this[string name, params object[] arguments] 
{
    get
    {
        var translation = _translations[name];

        if(arguments.Any()) 
        {
            var formatted = string.Format(translation, arguments); 

            return new LocalizedString(name, formatted, false);
        }

        return new LocalizedString(name, translation, false);
    }
}

這很完美,除了一件事: arguments總是空的。 沒有參數,即使我知道該方法會被命中(斷點會被命中)。

因此,我無法對抗內部調用的string.Format ,如果參數少於預期(在這種情況下只有 1 個參數),則會引發異常。

我想擴展我的代碼以在我的代碼中try/catch string.Format ,這樣我就可以記錄潛在的失敗,然后回## MISING ARGUMENT ##顯示密鑰,或者簡單地用## MISING ARGUMENT ##或類似的東西替換缺少的參數那。

我應該如何對抗這種情況? 奇怪的是,該方法被擊中了,但沒有參數。

您的代碼被命中但沒有參數的原因是來自此類的索引:Microsoft.AspNetCore.Mvc.Localization::HtmlLocalizer

    public virtual LocalizedHtmlString this[string name, params object[] arguments]
    {
        get
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            return ToHtmlString(_localizer[name], arguments);
        }
    }

如您所見,它不會調用 _localizer[name, arguments] 而是 _localizer[name]。

邏輯似乎是 ToHtmlString 創建並返回 LocalizedHtmlString 的實例,Value 有以下描述

    /// <summary>
    /// The original resource string, prior to formatting with any constructor arguments.
    /// </summary>
    public string Value { get; }

看起來您不應該對其進行格式化,而是讓 LocalizedHtmlString.WriteTo 方法進行格式化。

我也有自己的IStringLocalizer<TResourceSource>IHtmlLocalizer<TResourceSource> 我不確定你的行為是什么,但對我來說,當頁面呈現並且LocalizedHtmlString.WriteTo因參數計數不匹配而失敗時,它立即停止並且顯示部分呈現的任何內容並且沒有發生錯誤(從用戶的角度來看) . 但是,輸出窗口中有一些東西,這就是我確認LocalizedHtmlString.WriteTo問題的方式。

為了解決,我基本上采用給定的資源字符串並找到最高的參數替換。 然后,如果傳入的參數不包含足夠的參數,我會附加足夠的參數和一個虛擬字符串,OP 建議指示缺少參數,以便頁面呈現但在字符串中顯示“缺少”。

public virtual LocalizedHtmlString this[ string name ] => GetLocalizedString( name, new object[] { }, GetValue, IsResourceFound, GetLocalizedHtmlItem );

public virtual LocalizedHtmlString this[ string name, params object[] arguments ] 
{
    var ls = _localizer[name, arguments];

    if ( !ls.IsResourceNotFound( ls ) )
    {
        var matches = parameterCount.Matches( ls.Value );

        var expectedParameters = matches.Count > 0
            ? matches.Cast<Match>()
                .Max( m => int.Parse( m.Groups[ "number" ].Value ) + 1 )
            : 0;

        if ( arguments.Length < expectedParameters )
        {
            var protectedArgs =
                arguments.Concat(
                    Enumerable
                        .Range( arguments.Length, expectedParameters - arguments.Length )
                        .Select( p => $"{{MISSING PARAM #{p}}}" )
                ).ToArray();

            return _localizer[name, protectedArgs];
        }
    }

    return ls;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM