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 回答