[C#] DisplayNameAttribute का स्थानीकरण


Answers

हम कई भाषाओं के समर्थन के लिए कई विशेषताओं के लिए ऐसा कर रहे हैं हमने माइक्रोसॉफ्ट के लिए एक समान दृष्टिकोण लिया है, जहां वे अपने बेस एट्रिब्यूट को ओवरराइड करते हैं और वास्तविक स्ट्रिंग के बजाय संसाधन नाम पास करते हैं। संसाधन नाम का उपयोग फिर से वास्तविक स्ट्रिंग के लिए DLL संसाधनों में देखने के लिए किया जाता है।

उदाहरण के लिए:

class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
    private readonly string resourceName;
    public LocalizedDisplayNameAttribute(string resourceName)
        : base()
    {
      this.resourceName = resourceName;
    }

    public override string DisplayName
    {
        get
        {
            return Resources.ResourceManager.GetString(this.resourceName);
        }
    }
}

आप वास्तव में इस विशेषता का उपयोग करते हुए एक कदम आगे ले सकते हैं, और एक स्थैतिक कक्षा में स्थिरता के रूप में अपने संसाधन नाम निर्दिष्ट कर सकते हैं। इस तरह, आप जैसे घोषणाएं मिलती हैं

[LocalizedDisplayName(ResourceStrings.MyPropertyName)]
public string MyProperty
{
  get
  {
    ...
  }
}

अद्यतन करें
ResourceStrings तरह कुछ दिखाई देगा (ध्यान दें, प्रत्येक स्ट्रिंग एक संसाधन के नाम को संदर्भित करेगी जो वास्तविक स्ट्रिंग निर्दिष्ट करती है):

public static class ResourceStrings
{
    public const string ForegroundColorDisplayName="ForegroundColorDisplayName";
    public const string FontSizeDisplayName="FontSizeDisplayName";
}
Question

मैं PropertyGrid में प्रदर्शित गुण नामों को स्थानांतरित करने का एक तरीका तलाश रहा हूं प्रॉपर्टी का नाम DisplayNameAttribute विशेषता का उपयोग करके "ओवरराइड" हो सकता है। दुर्भाग्य से गुणों में निरंतर अभिव्यक्तियाँ नहीं हो सकतीं इसलिए मैं दृढ़ता से टाइप किए गए संसाधनों का उपयोग नहीं कर सकता जैसे कि:

class Foo
{
   [DisplayAttribute(Resources.MyPropertyNameLocalized)]  // do not compile
   string MyProperty {get; set;}
}

मुझे चारों ओर एक नज़र मिल गया था और कुछ सूचनाएं थी जो कि संसाधनों का उपयोग करने में सक्षम होने के लिए DisplayNameAttribute से वंशानुगत हो। मुझे कोड की तरह समाप्त होगा:

class Foo
{
   [MyLocalizedDisplayAttribute("MyPropertyNameLocalized")] // not strongly typed
   string MyProperty {get; set;}
}

हालांकि मैं दृढ़तापूर्वक टाइप किए हुए संसाधन लाभ खो देता हूं जो निश्चित रूप से अच्छी बात नहीं है तब मुझे DisplayNameResourceAttribute में मिला, जो हो सकता है कि मैं क्या चाहता हूं। लेकिन यह माइक्रोसॉफ्ट में होना चाहिए। विज़ुअल स्टूडियो। मॉडलिंग। डिज़ाइन नेमस्पेस और मुझे यह नाम स्थान के लिए जो संदर्भ शामिल करना है मैं नहीं पा रहा।

किसी को भी पता है कि एक अच्छा तरीका में DisplayName स्थानीयकरण प्राप्त करने का एक आसान तरीका है? या अगर माइक्रोसॉफ्ट का उपयोग करने के तरीके के रूप में दृश्य स्टूडियो के लिए प्रयोग करने लगता है?




प्रदर्शन विशेषता (System.ComponentModel.DataAnnotations से) और C # 6 में नाम () अभिव्यक्ति का उपयोग करते हुए, आपको स्थानीय और दृढ़तापूर्वक टाइप किए गए समाधान प्राप्त होंगे।

[Display(ResourceType = typeof(MyResources), Name = nameof(MyResources.UserName))]
public string UserName { get; set; }



मैं इस तरह से मेरे मामले में हल का उपयोग करता हूं

[LocalizedDisplayName("Age", NameResourceType = typeof(RegistrationResources))]
 public bool Age { get; set; }

कोड के साथ

public sealed class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
    private PropertyInfo _nameProperty;
    private Type _resourceType;


    public LocalizedDisplayNameAttribute(string displayNameKey)
        : base(displayNameKey)
    {

    }

    public Type NameResourceType
    {
        get
        {
            return _resourceType;
        }
        set
        {
            _resourceType = value;
            _nameProperty = _resourceType.GetProperty(base.DisplayName, BindingFlags.Static | BindingFlags.Public);
        }
    }

    public override string DisplayName
    {
        get
        {
            if (_nameProperty == null)
            {
                return base.DisplayName;
            }

            return (string)_nameProperty.GetValue(_nameProperty.DeclaringType, null);
        }
    }

}



मैं वीबी। नेट कोड के लिए माफी मांगता हूं, मेरी सी # थोड़ी सी जंगली है ... लेकिन आपको ये विचार मिलेगा, है ना?

सबसे पहले, एक नया वर्ग बनाएं: LocalizedPropertyDescriptor , जो कि PropertyDescriptor । इस तरह DisplayName संपत्ति को ओवरराइड करें:

Public Overrides ReadOnly Property DisplayName() As String
         Get
            Dim BaseValue As String = MyBase.DisplayName
            Dim Translated As String = Some.ResourceManager.GetString(BaseValue)
            If String.IsNullOrEmpty(Translated) Then
               Return MyBase.DisplayName
            Else
               Return Translated
           End If
    End Get
End Property

कुछ। संसाधन Some.ResourceManager संसाधन फ़ाइल के संसाधन Some.ResourceManager जिसमें आपके अनुवाद शामिल हैं।

इसके बाद, स्थानीय प्रॉपर्टी के साथ क्लास में ICustomTypeDescriptor को कार्यान्वित करें और ICustomTypeDescriptor विधि को ओवरराइड करें:

Public Function GetProperties() As PropertyDescriptorCollection Implements System.ComponentModel.ICustomTypeDescriptor.GetProperties
    Dim baseProps As PropertyDescriptorCollection = TypeDescriptor.GetProperties(Me, True)
    Dim LocalizedProps As PropertyDescriptorCollection = New PropertyDescriptorCollection(Nothing)

    Dim oProp As PropertyDescriptor
    For Each oProp In baseProps
        LocalizedProps.Add(New LocalizedPropertyDescriptor(oProp))
    Next
    Return LocalizedProps
End Function

अब आप 'DisplayName` विशेषता को एक संसाधन फ़ाइल में मान के संदर्भ को संग्रहीत करने के लिए उपयोग कर सकते हैं ...

<DisplayName("prop_description")> _
Public Property Description() As String

prop_description संसाधन फ़ाइल में कुंजी है




आप स्थिरांक उत्पन्न करने के लिए T4 का उपयोग कर सकते हैं मैंने एक लिखा था:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Xml.dll" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.XPath" #>
using System;
using System.ComponentModel;


namespace Bear.Client
{
 /// <summary>
 /// Localized display name attribute
 /// </summary>
 public class LocalizedDisplayNameAttribute : DisplayNameAttribute
 {
  readonly string _resourceName;

  /// <summary>
  /// Initializes a new instance of the <see cref="LocalizedDisplayNameAttribute"/> class.
  /// </summary>
  /// <param name="resourceName">Name of the resource.</param>
  public LocalizedDisplayNameAttribute(string resourceName)
   : base()
  {
   _resourceName = resourceName;
  }

  /// <summary>
  /// Gets the display name for a property, event, or public void method that takes no arguments stored in this attribute.
  /// </summary>
  /// <value></value>
  /// <returns>
  /// The display name.
  /// </returns>
  public override String DisplayName
  {
   get
   {
    return Resources.ResourceManager.GetString(this._resourceName);
   }
  }
 }

 partial class Constants
 {
  public partial class Resources
  {
  <# 
   var reader = XmlReader.Create(Host.ResolvePath("resources.resx"));
   var document = new XPathDocument(reader);
   var navigator = document.CreateNavigator();
   var dataNav = navigator.Select("/root/data");
   foreach (XPathNavigator item in dataNav)
   {
    var name = item.GetAttribute("name", String.Empty);
  #>
   public const String <#= name#> = "<#= name#>";
  <# } #>
  }
 }
}