3

次のようなローカライズされた属性に問題があります。

public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
    public LocalizedDisplayNameAttribute(string resourceId)
        : base(GetMessageFromResource(resourceId))
    { }

    private static string GetMessageFromResource(string resourceId)
    {
        var propertyInfo = typeof(Lockit).GetProperty(resourceId, BindingFlags.Static | BindingFlags.Public);
        return (string)propertyInfo.GetValue(null, null);
    }
}

この属性を持つプロパティを使用すると、PropertyGrid でローカライズされますが、現在の CultureInfo を変更すると、この PropertyGrid を再度作成しても更新されません。この属性を次の方法で手動で呼び出そうとしました。

foreach (PropertyInfo propertyInfo in myPropertiesInfoTab)
{
    object[] custom_attributes = propertyInfo.GetCustomAttributes(false);
}

プロパティ コンストラクターが呼び出されますが、新しく作成された PropertyGrid には、古いカルチャ表示名のプロパティがまだ含まれています (常に最初に作成された値と同じ値)。

アプリケーションを再起動すると機能しますが、これはしたくありません。解決策はありますか?

4

1 に答える 1

2

これは、単純だが完全な例で再現できます (名前にカウンターを追加するだけで、発生した各翻訳を表すことができます)。

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Show();
    Show();
}
static void Show()
{
    using(var grid = new PropertyGrid
        {Dock = DockStyle.Fill, SelectedObject = new Foo { Bar = "def"} })
    using(var form = new Form { Controls = { grid }})
    {
        form.ShowDialog();
    }
}

class Foo
{
    [CheekyDisplayName("abc")]
    public string Bar { get; set; }
}
public class CheekyDisplayNameAttribute : DisplayNameAttribute
{
    public CheekyDisplayNameAttribute(string resourceId)
    : base(GetMessageFromResource(resourceId))
    { }
    private static string GetMessageFromResource(string resourceId)
    {
        return resourceId + Interlocked.Increment(ref counter);
    }

    private static int counter;
}

これは、呼び出し間で属性がキャッシュされていることを示しています。DisplayNameおそらく、これを修正する最も簡単な方法は、クエリが実行されるまで翻訳を遅らせることです。

public class CheekyDisplayNameAttribute : DisplayNameAttribute
{
    public CheekyDisplayNameAttribute(string resourceId)
        : base(resourceId)
    { }
    private static string GetMessageFromResource(string resourceId)
    {
        return resourceId + Interlocked.Increment(ref counter);
    }
    public override string DisplayName
    {
        get { return GetMessageFromResource(base.DisplayName); }
    }
    private static int counter;
}

ただし、これは何度も呼び出される可能性があることに注意してください(表示ごとに 36 回)。キャッシュされたカルチャとともに値をキャッシュすることができます

    private CultureInfo cachedCulture;
    private string cachedDisplayName;
    public override string DisplayName
    {
        get
        {
            var culture = CultureInfo.CurrentCulture;
            if (culture != cachedCulture)
            {
                cachedDisplayName = GetMessageFromResource(base.DisplayName);
                cachedCulture = culture;
            }
            return cachedDisplayName;
        }
    }
于 2012-08-30T09:40:02.917 に答える