web-dev-qa-db-fra.com

Enum localisation

Comment localisez-vous les énumérations pour une ListBoxFor où plusieurs options sont possibles?

Par exemple, une enum qui contient des rôles:

public enum RoleType
{
    [Display(Description = "Administrator", ResourceType = typeof(Resource))]
    Administrator = 1,
    [Display(Description = "Moderator", ResourceType = typeof(Resource))]
    Moderator = 2,
    [Display(Description = "Webmaster", ResourceType = typeof(Resource))]
    Webmaster = 3,
    [Display(Description = "Guest", ResourceType = typeof(Resource))]
    Guest = 4,
    Etc.... = 5,
}

J'ai vu cela se faire avec dropdownlist/selectlists. Mais existe-t-il un moyen de faire cela pour une liste à sélection multiple?

[MODIFIER]

Voici comment je voudrais l'utiliser, c'est comme cela que ça fonctionne maintenant, mais que cela ne se traduit pas dans une autre langue:

var roles = from role r in Enum.GetValues(typeof(RoleType))
            select new
            {
               Id = (int)Enum.Parse(typeof(RoleType), r.ToString()),
               Name = r.ToString()
            };

searchModel.roles = new MultiSelectList(roles, "Id", "Name");

Remarque: j'ai renommé l'énum de Role en RoleType.

49
Quoter

Vous pouvez implémenter un attribut de description.

public class LocalizedDescriptionAttribute : DescriptionAttribute
{
     private readonly string _resourceKey;
    private readonly ResourceManager _resource;
    public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
    {
        _resource = new ResourceManager(resourceType);
        _resourceKey = resourceKey;
    }

    public override string Description
    {
        get
        {
            string displayName = _resource.GetString(_resourceKey);

            return string.IsNullOrEmpty(displayName)
                ? string.Format("[[{0}]]", _resourceKey)
                : displayName;
        }
    }
}

public static class EnumExtensions
{
    public static string GetDescription(this Enum enumValue) 
    {
        FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

        DescriptionAttribute[] attributes =
            (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute),
            false);

        if (attributes != null &&
            attributes.Length > 0)
            return attributes[0].Description;
        else
            return enumValue.ToString();
    }
}

Définissez-le comme ceci:

public enum Roles
{
    [LocalizedDescription("Administrator", typeof(Resource))]
    Administrator,
...
}

Et utilisez-le comme ceci:

var roles = from RoleType role in Enum.GetValues(typeof(RoleType))
                    select new
                    {
                        Id = (int)role,
                        Name = role.GetDescription()
                    };
 searchModel.roles = new MultiSelectList(roles, "Id", "Name");
63
eluxen

J'ai résolu le problème en créant un EnumExtension que j'utilise à mon avis. Cette extension recherche un fichier de ressource appelé "EnumResources.resx" et recherche la ressource selon la convention de dénomination suivante {Nom de EnumType} _ {Valeur de l'énum passée}. Si la clé de ressource est manquante, la valeur de la ressource encapsulée entre crochets [[EnumValue]] sera affichée. De cette façon, il est facile de trouver un Enum "non traduit" dans votre vue. Cela vous aide également à vous rappeler si vous avez oublié de mettre à jour le fichier de ressources après un changement de nom ou autre.

public static class EnumExtensions
{
    public static string GetDisplayName(this Enum e)
    {
        var rm = new ResourceManager(typeof (EnumResources));
        var resourceDisplayName = rm.GetString(e.GetType().Name + "_" + e);

        return string.IsNullOrWhiteSpace(resourceDisplayName) ? string.Format("[[{0}]]", e) : resourceDisplayName;
    }
}

Le fichier de ressources ressemble à ceci: Resource file

Usage:

<div>@ContractStatus.Created.GetDisplayName()</div>
26
disco

Il existe un moyen d'utiliser des attributs pour spécifier une chaîne à utiliser pour les énumérations lors de leur affichage, mais nous l'avons trouvée beaucoup trop complexe lorsque vous avez dû gérer la localisation.

Donc, ce que nous faisons habituellement pour les énumérations qui doivent être localisées est d’écrire une classe d’extension qui fournit une méthode pour obtenir le nom traduit. Vous pouvez simplement utiliser un commutateur qui renvoie des chaînes à partir des ressources habituelles. De cette façon, vous fournissez des chaînes traduites pour les énumérations via les ressources, comme vous le feriez pour d'autres chaînes.

Par exemple:

public enum Role
{
    Administrator,
    Moderator,
    Webmaster,
    Guest
}

public static class RoleExt
{
    public static string AsDisplayString(this Role role)
    {
        switch (role)
        {
            case Role.Administrator: return Resources.RoleAdministrator;
            case Role.Moderator:     return Resources.RoleModerator;
            case Role.Webmaster:     return Resources.RoleWebmaster;
            case Role.Guest:         return Resources.RoleGuest;

            default: throw new ArgumentOutOfRangeException("role");
        }
    }
}

Que vous pouvez utiliser comme ceci:

var role = Role.Administrator;
Console.WriteLine(role.AsDisplayString());

Si vous conservez l'implémentation de la classe RoleExt à côté de l'implémentation enum Role, celle-ci fera partie intégrante de l'interface pour Role. Bien sûr, vous pouvez également ajouter à cette classe toute autre extension utile pour l’énumération.

[MODIFIER]

Si vous souhaitez gérer plusieurs paramètres d'indicateur ("Administrateur, Modérateur et Webmaster"), vous devez procéder différemment:

[Flags]
public enum Roles
{
    None          = 0,
    Administrator = 1,
    Moderator     = 2,
    Webmaster     = 4,
    Guest         = 8
}

public static class RolesExt
{
    public static string AsDisplayString(this Roles roles)
    {
        if (roles == 0)
            return Resources.RoleNone;

        var result = new StringBuilder();

        if ((roles & Roles.Administrator) != 0)
            result.Append(Resources.RoleAdministrator + " ");

        if ((roles & Roles.Moderator) != 0)
            result.Append(Resources.RoleModerator + " ");

        if ((roles & Roles.Webmaster) != 0)
            result.Append(Resources.RoleWebmaster + " ");

        if ((roles & Roles.Guest) != 0)
            result.Append(Resources.RoleGuest + " ");

        return result.ToString().TrimEnd();
    }
}

Ce que vous pourriez utiliser comme ceci:

Roles roles = Roles.Administrator | Roles.Guest | Roles.Moderator;
Console.WriteLine(roles.AsDisplayString());

Fichiers de ressources

Les fichiers de ressources sont la manière dont vous internationalisez vos chaînes. Pour plus d'informations sur leur utilisation, voir ici:

http://msdn.Microsoft.com/en-us/library/vstudio/aa992030%28v=vs.100%29.aspxhttp://msdn.Microsoft.com/en- us/bibliothèque/vstudio/756hydy4% 28v = vs.100% 29.aspx

8
Matthew Watson

Vous pouvez utiliser votre valeur enum pour faire ce que vous voulez.

public enum Roles
{
    Administrator = 0,
    Moderator = 1 ,
    Webmaster  = 2,
    Guest = 3 ,
    Etc.... = 4 
}

Lorsque vous souhaitez obtenir l'énumération sélectionnée dans la zone de liste, vous récupérez l'élément de la liste, puis le numéro d'énum associé.

Ensuite, vous allez convertir cela en un élément enum comme celui-ci. 

Roles myrol = (Roles) i

(i est associé à vale pour cet exemple)

Conversion de l'élément enum en entier et la valeur entière en élément enum 

 Enum Item to Integer----- 
    int i =  (int)Roles.Admin ;
    Integer to enum Itenm
    Roles r = (Roles)i ; 

     //Getting the name of the enum
     string role =  Role.Admin.ToString() 

SI vous ajoutez à une table de hachage, vous pouvez le faire de cette façon 

Hashtable h = new Hashtable() ; 
h.Items.Add((int)Roles.Admin , Roles.Admin.ToStrinng() ) ;
h.Items.Add((int)Roles.Local , Roles.Local.ToStrinng() ) ; 

lorsque vous choisissez un élément de la table de hachage, reconvertissez-le en élément Enum et utilisez-le où vous voulez. Vous pouvez utiliser la même méthode pour remplir des Datatables/Comboboxes, des listes déroulantes, etc.

2
Kas

Un des problèmes avec la traduction/localisation d'énums est que vous devez non seulement les traduire pour les afficher, mais également les analyser à la valeur d'énum. Le fichier C # suivant explique comment j’ai surmonté les problèmes de traduction bidirectionnelle d’énums. Pardonnez les commentaires excessifs, mais je suis plutôt verbeux sur mes créations.

//
// EnumExtensions.cs  
//
using System;
using System.Collections.Generic;

namespace EnumExtensionsLibrary
{
    /// <summary>
    /// The functions in this class use the localized strings in the resources
    /// to translate the enum value when output to the UI and reverse--
    /// translate when receiving input from the UI to store as the actual
    /// enum value.
    /// </summary>
    /// 
    /// <Note>
    /// Some of the exported functions assume that the ParserEnumLocalizationHolder
    /// and ToStringEnumLocalizationHolder dictionaries (maps) may contain the enum 
    /// types since they callthe Initialize methods with the input type before executing.
    /// </Note>
    public static class EnumExtensions
    {
        #region Exported methods
        /// <summary>
        /// Save resource from calling project so that we can look up enums as needed.
        /// </summary>
        /// <param name="resourceManager">Where we fish the translated strings from</param>
        /// <remarks>
        /// We do not have access to all of the resources from the other projects directly,
        /// so they must be loaded from the code from within the project.
        /// </remarks>
        public static void RegisterResource(System.Resources.ResourceManager resourceManager)
        {
            if (!MapOfResourceManagers.Contains(resourceManager))
                MapOfResourceManagers.Add(resourceManager);
        }

        /// <summary>
        /// Parses the localized string value of the enum by mapping it 
        /// to the saved enum value
        /// </summary>
        /// <remarks>
        /// In some cases, string for enums in the applications may not be translated to the
        /// localized version (usually when the program presets parameters).  If the enumMap
        /// doesn't contain the value string, we call to Enum.Parse() to handle the conversion
        /// or throw an exception.
        /// </remarks>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <exception cref="ArgumentNullException"> enumType or value is null.</exception>
        /// <exception cref="ArgumentException"> enumType is not an Enum. value is either an 
        /// empty string or only contains white space, value is a name, but not one of the 
        /// named constants defined for the enumeration.</exception>
        /// <exception cref="ArgumentNullException">enumType or value is null.</exception>
        /// <returns>
        /// The enum value that matched the input string if found.  If not found, we call 
        /// Enum.Parse to handle the value.
        /// </returns>
        public static T ParseEnum<T>(this string value) where T : struct
        {
            ParserInitialize(typeof(T));
            var enumMap = ParserEnumLocalizationHolder[typeof(T)];
            if (enumMap.ContainsKey(value))
                return (T) enumMap[value];
            return (T)Enum.Parse(typeof(T), value); 
        }

        /// <summary>
        /// Parses the localized string value of the enum by mapping it 
        /// to the saved enum value.  
        /// </summary>
        /// <remarks>
        /// In some cases, string for enums in the applications may not be translated to the
        /// localized version (usually when the program presets parameters).  If the enumMap
        /// doesn't contain the value string, we call to Enum.TryParse() to handle the 
        /// conversion. and return.
        /// </remarks>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="result"></param>
        /// <returns>
        /// Returns true if the enum mapping contains the localized string value and the data 
        /// in the returned result parameter will be a valid value of that enum type. if the
        /// string value is not mapped, then calls Enum.TryParse to handle the conversion and 
        /// return result.
        /// </returns>
        public static bool TryParseEnum<T>(this string value, out T result) where T : struct
        {
            ParserInitialize(typeof(T));
            var enumMap = ParserEnumLocalizationHolder[typeof(T)];
            if (!enumMap.ContainsKey(value))
                return Enum.TryParse(value, out result);
            result = (T)enumMap[value];
            return true;
        }

        /// <summary>
        /// Converts the enum value to a localized string.
        /// </summary>
        /// <typeparam name="T">must be an enum to work</typeparam>
        /// <param name="value">is an enum</param>
        /// <returns>
        /// The localized string equivalent of the input enum value
        /// </returns>
        public static string EnumToString<T>(this T value) where T : struct
        {
            ToStringInitialize(typeof(T));
            var toStringMap = ToStringEnumLocalizationHolder[typeof(T)];
            return toStringMap.ContainsKey(value) ? toStringMap[value] : value.ToString();

            //return EnumDescription(value);
        }

        /// <summary>
        /// Gathers all of the localized translations for each 
        /// value of the input enum type into an array
        /// </summary>
        /// <remarks>
        /// The return array from Type.GetEnumValues(), the array elements are sorted by 
        /// the binary values (that is, the unsigned values) of the enumeration constants.
        /// </remarks>
        /// <param name="enumType"></param>
        /// <exception cref="ArgumentException"> The current type is not an enumeration.</exception>
        /// <returns>
        /// A string array with the localized strings representing
        /// each of the values of the input enumType.
        /// </returns>
        public static string[] AllDescription(this Type enumType)
        {
            ToStringInitialize(enumType);
            var descriptions = new List<string>();
            var values = enumType.GetEnumValues();
            var toStringMap = ToStringEnumLocalizationHolder[enumType];
            foreach (var value in values)
            {
                descriptions.Add(toStringMap.ContainsKey(value) ? toStringMap[value] : value.ToString());
            }
            return descriptions.ToArray();
        }
        #endregion

        #region Helper methods
        /// <summary>
        /// Translates an enum value into its localized string equivalent
        /// </summary>
        /// <remarks>
        /// This assumes that the "name" for the localized string in the 
        /// resources will look like "enum-type-name""value".  For example,  
        /// if I have an enum setup as:
        /// 
        ///     enum Days {Sat, Sun, Mon, Tue, Wed, Thu, Fri};
        /// 
        /// the value "Sun" in the enum must have the name: "DaysSun"
        /// in the resources. The localized (translated) string will
        /// be in the value field.  E.g.,
        ///
        ///  <data name="DaysSun" xml:space="preserve">
        /// <value>Sunday</value>
        ///  </data>    
        /// 
        /// 2nd note: there may be multiple resources to pull from.
        /// Will look in each resource until we find a match or 
        /// return null.
        /// </remarks>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumType">the enum type</param>
        /// <param name="value">the specific enum value</param>
        /// <returns>
        /// If the enum value is found in the resources, then return 
        /// that string.  If not, then return null. 
        /// </returns>
        private static string LocalEnumDescription<T>(Type enumType, T value)
        {
            foreach (var resourceManager in MapOfResourceManagers)
            {
                // The following live line uses string interpolation to perform:
                //var rk = string.Format("{0}{1}", enumType.Name, value);
                var rk = $"{enumType.Name}{value}";

                // Given the above string formatting/interpolation, neither the enum.Name 
                // nor the value will have a '.' so we do not have to remove it.
                var result = resourceManager.GetString(rk);
                if (!string.IsNullOrEmpty(result))
                    return result;
            }
            return null;
        }

        /// <summary>
        /// Initializes the mapping of the enum type to its mapping of localized strings to 
        /// the enum's values.
        /// </summary>
        /// <remarks>
        /// The reason for each enum type to have a mapping from the localized string back 
        /// to its values is for ParseEnum and TryParseEnum to quickly return a value rather
        /// than doing a lengthy loop comparing each value in the resources.
        /// 
        /// Also, we only map the corresponding resource string if it exists in the resources.
        /// If not in the resources, then we call the Enum methods Parse() and TryParse() to
        /// figure the results and throw the appropriate exception as needed.
        /// </remarks>
        /// 
        /// <param name="enumType"></param>
        private static void ParserInitialize(Type enumType)
        {
            if (!ParserEnumLocalizationHolder.ContainsKey(enumType))
            {
                var values = enumType.GetEnumValues();  // See remark for AllDescription().
                var enumMap = new Dictionary<string, object>();
                foreach (var value in values)
                {
                    var description = LocalEnumDescription(enumType, value);
                    if (description != null)
                        enumMap[description] = value;
                }
                ParserEnumLocalizationHolder[enumType] = enumMap;
            }
        }

        /// <summary>
        /// Initializes the mapping of the enum type to its mapping of the enum's values
        /// to their localized strings.
        /// </summary>
        /// <remarks>
        /// The reason for each enum type to have a mapping from the localized string to its
        /// values is for AllDescription and EnumToString to quickly return a value rather 
        /// than doing a lengthy loop runing through each of the resources.
        /// 
        /// Also, we only map the corresponding resource string if it exists in the resources.
        /// See the EnumDescription method for more information.
        /// </remarks>
        /// 
        /// <param name="enumType"></param>
        private static void ToStringInitialize(Type enumType)
        {
            if (!ToStringEnumLocalizationHolder.ContainsKey(enumType))
            {
                var values = enumType.GetEnumValues();  // See remark for AllDescription().
                var enumMap = new Dictionary<object, string>();
                foreach (var value in values)
                {
                    var description = LocalEnumDescription(enumType, value);
                    if (description != null)
                        enumMap[value] = description;
                }
                ToStringEnumLocalizationHolder[enumType] = enumMap;
            }
        }
        #endregion

        #region Data
        private static readonly List<System.Resources.ResourceManager> MapOfResourceManagers =
            new List<System.Resources.ResourceManager>();
        private static readonly Dictionary<Type, Dictionary<string, object>> ParserEnumLocalizationHolder =
            new Dictionary<Type, Dictionary<string, object>>();
        private static readonly Dictionary<Type, Dictionary<object, string>> ToStringEnumLocalizationHolder =
            new Dictionary<Type, Dictionary<object, string>>();
        #endregion
    }
}

Cela n'exige pas d'attribut avant chaque valeur énumérée, mais exige que l'attribut name de votre chaîne énumérée traduite dans les ressources soit formaté de sorte qu'il s'agisse d'une concaténation du nom énumération et du type énumération. Voir le commentaire ci-dessus la méthode LocalEnumDescription pour plus d'informations. En outre, il préserve les traductions des énumérations (en avant et en arrière) en mappant leurs traductions de sorte que nous n'avons pas besoin de rechercher la traduction à chaque fois que nous rencontrons une valeur enum.

Heureusement, il est assez facile à comprendre et à utiliser.

1
Jim Lonero

La méthode d'extension ci-dessous ça a fonctionné pour moi.

    public static string GetDisplayValue(this Enum value)
    {
        try
        {
            var fieldInfo = value.GetType().GetField(value.ToString());
            var descriptionAttributes = fieldInfo.GetCustomAttributes(typeof(DisplayAttribute), false) as DisplayAttribute[];

            if (descriptionAttributes == null || descriptionAttributes.Length == 0) return value.ToString();

            if (descriptionAttributes[0].ResourceType != null)
            {
                var resource = descriptionAttributes[0].ResourceType.GetProperty("ResourceManager").GetValue(null) as ResourceManager;
                return resource.GetString(descriptionAttributes[0].Name);
            }
            else
            {
                return descriptionAttributes[0].Name;
            }
        }
        catch
        {
            return value.ToString();
        }
    }

Je Holpe aide.

1
jmsandy

Une version de @ eluxen's answer fonctionne pour certaines bibliothèques portables (PCL) (spécifiquement pour Profile47) où la solution originale ne fonctionne pas. Deux problèmes ont été résolus: DescriptionL'attribut n'est pas disponible dans les bibliothèques portables et le problème signalé par @Jitendra Pancholi avec une erreur "Impossible de trouver des ressources" est résolu.

public class LocalizedDescriptionAttribute : Attribute
{
    private readonly string _resourceKey;
    private readonly Type _resourceType;
    public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
    {
        _resourceType = resourceType;
        _resourceKey = resourceKey;
    }

    public string Description
    {
        get
        {
            string displayName = String.Empty;
            ResourceManager resMan = _resourceType.GetProperty(
                @"ResourceManager", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null, null) as ResourceManager;
            CultureInfo culture = _resourceType.GetProperty(
                    @"Culture", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null, null) as CultureInfo;

            if (resMan != null)
            {
                displayName = resMan.GetString(_resourceKey, culture);
            }

            var ret = string.IsNullOrEmpty(displayName) ? string.Format("[[{0}]]", _resourceKey) : displayName;
            return ret;
        }
    }
}

Pour utilisation, voir réponse originale . Et si vous ne rencontrez aucun problème, j’utiliserai quand même la réponse initiale car elle ne contient pas de solution de rechange par réflexion.

1
avitenberg

Une autre possibilité consiste à créer un stockage de noms globaux global comme extension de classe sur Enum class

// Enum display names
public static class EnumDisplayNames {
  // Display name storage
  private static Dictionary<Type, Dictionary<Enum, String>> s_Names = 
    new Dictionary<Type, Dictionary<Enum, String>>();

  // Display name for the single enum's option
  private static String CoreAsDisplayName(Enum value) {
    Dictionary<Enum, String> dict = null;

    if (s_Names.TryGetValue(value.GetType(), out dict)) {
      String result = null;

      if (dict.TryGetValue(value, out result))
        return result;
      else
        return Enum.GetName(value.GetType(), value);
    }
    else
      return Enum.GetName(value.GetType(), value);
  }

  // Register new display name
  public static void RegisterDisplayName(this Enum value, String name) {
    Dictionary<Enum, String> dict = null;

    if (!s_Names.TryGetValue(value.GetType(), out dict)) {
      dict = new Dictionary<Enum, String>();

      s_Names.Add(value.GetType(), dict);
    }

    if (dict.ContainsKey(value))
      dict[value] = name;
    else
      dict.Add(value, name);
  }

  // Get display name
  public static String AsDisplayName(this Enum value) {
    Type tp = value.GetType();

    // If enum hasn't Flags attribute, just put vaue's name 
    if (Object.ReferenceEquals(null, Attribute.GetCustomAttribute(tp, typeof(FlagsAttribute))))
      return CoreAsDisplayName(value);

    // If enum has Flags attribute, enumerate all set options
    Array items = Enum.GetValues(tp);

    StringBuilder Sb = new StringBuilder();

    foreach (var it in items) {
      Enum item = (Enum) it;

      if (Object.Equals(item, Enum.ToObject(tp, 0)))
        continue;

      if (value.HasFlag(item)) {
        if (Sb.Length > 0)
          Sb.Append(", ");
        Sb.Append(CoreAsDisplayName(item));
      }
    }

    Sb.Insert(0, '[');

    Sb.Append(']');

    return Sb.ToString();
  }
}

L'utilisation possible est très simple, par exemple:

  public enum TestEnum {
    None,
    One,
    Two,
    Three
  }

  [Flags]
  public enum TestOptions {
    None = 0,
    One = 1,
    Two = 2,
    Three = 4
  }

  ...

  // Let them be in German (for demonstration only)... 
  TestEnum.None.RegisterDisplayName("Nichts");
  TestEnum.One.RegisterDisplayName("Eins");
  TestEnum.Two.RegisterDisplayName("Zwei");
  TestEnum.Three.RegisterDisplayName("Drei");

  // Usually, you obtain display names from resources:
  // TestEnum.None.RegisterDisplayName(Resources.NoneName);
  // ...

  TestOptions.None.RegisterDisplayName("-");
  TestOptions.One.RegisterDisplayName("bit 0 set");
  TestOptions.Two.RegisterDisplayName("bit 1 set");
  TestOptions.Three.RegisterDisplayName("bit 2 set");
  TestOptions.Four.RegisterDisplayName("bit 3 set");

  ...

  TestEnum v = TestEnum.Two;
  String result = v.AsDisplayName(); // <- "Zwei"

  TestOptions o = TestOptions.One | TestOptions.Three | TestOptions.Four;
  String result2 = o.AsDisplayName(); // <- "[bit 0 set, bit 2 set, bit 3 set]"
0
Dmitry Bychenko
public enum RoleEnum
{
    Administrator = 4,
    Official = 1,
    Trader = 3,
    HeadOfOffice = 2
}
public static class RoleEnumExtension
{
    private static readonly ResourceManager Resource =
        new ResourceManager("Project.CommonResource", typeof(CommonResource).Assembly);

    public static string Display(this RoleEnum role)
    {
        return Resource.GetString("RoleType_" + role);
    }
}

Vous pouvez l'utiliser comme

RoleEnum.Administrator.Display()

J'espère que cela aidera à quelqu'un

0
tech-gayan

Les solutions ci-dessus avec LocalizedDescriptionAttribute le lisent à partir de la langue actuelle du programme. Parfait pour un client, pas si flexible pour un côté serveur quand vous voulez passer la langue en paramètre.

J'ai donc étendu la solution eluxen avec LocalizedDescriptionAttribute en ajoutant une autre méthode:

    /// <summary>
    /// Gets the description, stored in this attribute, reading from the resource using the cultureInfo defined by the language!
    /// </summary>
    /// <param name="language">The language.</param>
    /// <returns>Description for the given language if found; the default Description or ressourceKey otherwise</returns>
    public string GetDescription(string language)
    {
        return resource.GetStringFromResourceForLanguage(resourceKey, language, Description);
    }

    public static string GetStringFromResourceForLanguage(this ResourceManager resourceManager, string resourceKey, string language, string defaultValue = null)
    {
        if (string.IsNullOrEmpty(defaultValue))
            defaultValue = resourceKey;
        try
        {
            CultureInfo culture = CultureInfo.GetCultureInfo(language);
            string displayName = resourceManager.GetString(resourceKey, culture);
            return !string.IsNullOrEmpty(displayName) ? displayName : defaultValue;
        }
        catch // any, not only CultureNotFoundException
        {
            return defaultValue;
        }
    }

Avec l'extension GetDescription également avec le paramètre language:

            bool hasLanguage = !string.IsNullOrEmpty(language);
            if (hasLanguage)
            {
                var attribute = (LocalizedDescriptionAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(LocalizedDescriptionAttribute));
                if (attribute != null)
                {
                    description = attribute.GetDescription(language);
                }
                else
                    hasLanguage = false;
            }
            if (!hasLanguage)
            {
                var attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(fieldInfo, typeof(DescriptionAttribute));
                if (attribute != null)
                {
                    description = attribute.Description;
                }
            }

Et finalement, je préfère éviter toute chaîne dans l'utilisation d'attribut, en utilisant nameof.

public enum QualityPersonInfo
{
    Ok = 0,
    [LocalizedDescription(nameof(QualityStrings.P1), typeof(QualityStrings))]
    Duplicate = 1,
    [LocalizedDescription(nameof(QualityStrings.P2), typeof(QualityStrings))]
    IdMissing = 2,
}

que j'utilise dans mon code comme suit:

 QualityPersonInfo status = QualityPersonInfo.IdMissing; 
 var description = status.GetDescription("ch-DE");
0
EricBDev

Je l'utilise actuellement, j'espère que ça aide !:

    /// <summary>
    ///  Retrieves a translated value from an enumerated list.
    /// </summary>
    /// <param name="value">Enum</param>
    /// <param name="resource">string</param>
    /// <returns>string</returns>
    protected string GetTranslatedEnum(Enum value, string resource)
    {
        string path = String.Format("Resources.{0}", resource);

        ResourceManager resources = new ResourceManager(path, global::System.Reflection.Assembly.Load("App_GlobalResources"));

        if (resources != null) {
            return resources.GetString(value.ToString());
        } else {
            return value.ToString();
        }
    }

Création d'un fichier .resx nommé " App_GlobalResources\ProductNames.resx ".

Usage:

// Convert the ProductId integer on the item to its Enum equivalent.
Products product = (Products) item.ProductId;

string productName = this.GetTranslatedEnum(product, "ProductNames");
0
Steve Bauman

Même réponse que la réponse acceptée mais sans avertissements d'analyse de code

 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification ="Resourcetype is only needed to instantiate Resource manager, and ResourceManager is exposed")]
[AttributeUsage(AttributeTargets.All)]
public sealed class LocalizedDescriptionAttribute 
    : DescriptionAttribute
{
    private readonly string _resourceKey;
    private readonly ResourceManager _resourceManager;

    public LocalizedDescriptionAttribute(string resourceKey, Type resourceType)
    {
        _resourceManager = new ResourceManager(resourceType);
        _resourceKey = resourceKey;
    }

    public string ResourceKey
    {
        get { return _resourceKey; }
    }

    public ResourceManager ResourceManager
    {
        get { return _resourceManager; }
    }

    public override string Description
    {
        get
        {
            string displayName = _resourceManager.GetString(_resourceKey);
            return string.IsNullOrEmpty(displayName)? string.Format(CultureInfo.CurrentUICulture ,"[[{0}]]", _resourceKey) : displayName;
        }
    }
}

public static class EnumExtensions
{
    public static string GetDescription(this Enum enumValue)
    {
        if (enumValue == null)
        {
            throw new ArgumentNullException("enumValue");
        }
        FieldInfo fi = enumValue.GetType().GetField(enumValue.ToString());

        DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return enumValue.ToString();
        }
    }
}
0
Martijn