Non sono sicuro di cosa si intende per "questo è più complessa di quanto la mia soluzione ideale". Ho un modo per farlo diverso dal tuo, ma potrebbe non essere meno complesso. Direi che il mio modo coinvolge più overhead in primo piano, ma paga sempre di più lo si utilizza nella vostra applicazione. Prepara la tua applicazione per essere localizzabile e significa che non devi aggiungere attributi a ciascun valore enum.
1) Fare un cache Resource Manager
Questa parte è facoltativa; tuttavia, se si utilizzano più file di risorse, molte volte, come faccio io, questo potrebbe aumentare le prestazioni riducendo la quantità di riflessione eseguita.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
namespace AppResourceLib.Public.Reflection
{
internal static class ResourceManagerCache
{
private static Dictionary<Type, ResourceManager> _resourceManagerMap =
new Dictionary<Type, ResourceManager>();
public static ResourceManager GetResourceManager(Type resourceType)
{
ResourceManager resourceManager = null;
// Make sure the type is valid.
if (null != resourceType)
{
// Try getting the cached resource manager.
if (!ResourceManagerCache._resourceManagerMap.TryGetValue(resourceType, out resourceManager))
{
// If it is not in the cache create it.
resourceManager = resourceType.InvokeMember(
"ResourceManager",
(BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic),
null,
null,
null) as ResourceManager;
// If it was created, add the resource manager to the cache.
if (null != resourceManager)
{
ResourceManagerCache._resourceManagerMap.Add(resourceType, resourceManager);
}
}
}
return resourceManager;
}
}
}
2) Creare una localizzata Descrizione Attributo
Questo è l'attributo che si applica al tipo Enum. La cosa interessante di questo è che non devi aggiungere un attributo a ogni enumerazione, solo una volta sopra la dichiarazione del tipo enum.
using System;
using System.ComponentModel;
namespace AppResourceLib.Public.Reflection
{
/// <summary>
/// A resource type attribute that can be applied to enumerations.
/// </summary>
[AttributeUsage(AttributeTargets.Enum)]
public sealed class LocalizedDescriptionAttribute : Attribute
{
/// <summary>
/// The type of resource associated with the enum type.
/// </summary>
private Type _resourceType;
public LocalizedDescriptionAttribute(Type resourceType)
{
this._resourceType = resourceType;
}
/// <summary>
/// The type of resource associated with the enum type.
/// </summary>
public Type ResourceType
{
get
{
return this._resourceType;
}
}
}
}
3) Creare localizzati Descrizione Converter
Questo converte il valore enum nella stringa si darà nel risorsa stringhe (RESX) file.
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Windows.Data;
namespace AppResourceLib.Public.Reflection
{
[ValueConversion(typeof(Object), typeof(String))]
public class LocalizedDescriptionConverter : IValueConverter
{
public Object Convert(Object value, Type targetType, Object param, CultureInfo cultureInfo)
{
String description = null;
if (null != value)
{
// If everything fails then at least return the value.ToString().
description = value.ToString();
// Get the LocalizedDescriptionAttribute of the object.
LocalizedDescriptionAttribute attribute =
value.GetType().GetCustomAttribute(typeof(LocalizedDescriptionAttribute))
as LocalizedDescriptionAttribute;
// Make sure we found a LocalizedDescriptionAttribute.
if (null != attribute)
{
ResourceManager resourceManager =
ResourceManagerCache.GetResourceManager(attribute.ResourceType);
if (null != resourceManager)
{
// Use the ResourceManager to get the description you gave the object value.
// Here we just use the object value.ToString() (the name of the object) to get
// the string in the .resx file. The only constraint here is that you have to
// name your object description strings in the .resx file the same as your objects.
// The benefit is that you only have to declare the LocalizedDescriptionAttribute
// above the object type, not an attribute over every object.
// And this way is localizable.
description = resourceManager.GetString(value.ToString(), cultureInfo);
String formatString = (param as String);
// If a format string was passed in as a parameter,
// make a string out of that.
if (!String.IsNullOrEmpty(formatString))
{
formatString = formatString.Replace("\\t", "\t");
formatString = formatString.Replace("\\n", "\n");
formatString = formatString.Replace("\\r", "\r");
description = String.Format(formatString, value.ToString(), description);
}
}
}
}
return description;
}
public Object ConvertBack(Object value, Type targetType, Object param, CultureInfo cultureInfo)
{
throw new NotImplementedException();
return null;
}
}
}
4) Creazione di una risorsa (.resx) sul file String
Ora si desidera creare un file di risorse che conterrà le descrizioni desiderate per il vostro stile di valore della chiave Enums. Quello che intendo con questo è che nella colonna "Nome" delle risorse stringa si inserisce il nome esatto delle singole enumerazioni e nella colonna "Valore" si inserisce la stringa che si desidera ottenere quando si converte l'enumerazione.
Ad esempio, supponiamo di avere i seguenti Enum.
public enum MyColors
{
Black,
Blue,
White
}
Allora il vostro file di risorse stringa sarebbe simile a questa ...
Nome | Valore
Nero | A Dark Color
Blu | Un bel colore
Bianco | Un colore luminoso
5) Creare enumerazioni con attributi
Ora abbiamo finalmente fare la dichiarazione Enum con l'LocalizedDescription. Il parametro che si passa all'attributo LocalizedDescription è il tipo del file di risorse stringa. Ora, quando viene utilizzato il convertitore, vedrà l'attributo del tipo di enum, otterrà il file di risorse, cercherà la stringa di chiavi che corrisponde al valore di stringa del particolare valore enum e restituirà il valore dal file di risorse come stringa convertita.
using AppResourceLib.Public;
using AppResourceLib.Public.Reflection;
namespace MyEnums
{
[LocalizedDescription(typeof(MyColorStrings))]
public enum MyColors
{
Black,
Blue,
White
}
}
Il principale svantaggio di questo approccio è che esso funziona solo se i tasti "Nome" nel file di risorse corrispondono ai nomi dei vostri valori enum. Questo è l'unico modo per fare riferimento a valori stringa in un file di risorse senza assegnare a ciascun enum un attributo di descrizione. Quindi, come lo usi per visualizzare i valori? Ecco un esempio ...
Nel codice xaml, si desidera creare un fornitore di dati per ottenere i valori dell'enumerazione sul proprio elemento dell'interfaccia utente (sto utilizzando un ComboBox qui ...). Quindi vorrai rendere disponibile il convertitore e template il tuo elemento UI per usare il convertitore enum. Quindi ecco qui ...
<!-- Enum Colors -->
<ObjectDataProvider x:Key="MyColorEnums"
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="MyColors"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<!-- Enum Type Converter -->
<LocalizedDescriptionConverter x:Key="EnumConverter"/>
<!-- Dropdown Expand ComboBox Template -->
<DataTemplate x:Key="MyColorsComboBoxTemplate">
<Label Content="{Binding Path=., Mode=OneWay,
Converter={StaticResource EnumConverter}}"
Height="Auto" Margin="0" VerticalAlignment="Center"/>
</DataTemplate>
<!-- And finally the ComboBox that will display all of your enum values
but will use the strings from the resource file instead of enum.ToString() -->
<ComboBox Width="80" HorizontalAlignment="Left"
ItemTemplate="{StaticResource MyColorsComboBoxTemplate}"
ItemsSource="{Binding Source={StaticResource MyColorEnums}}">
Wow, scusa, è così lungo. Non sono sicuro che sia troppo complesso per te, ma è un'altra opzione. Spero che sia d'aiuto!
Forse dovresti provare questo metodo: http://en.wikipedia.org/wiki/Rubber_duck_debugging – espais
possibile duplicato di [Come sovrascrivo ToString in en # C?] (Http://stackoverflow.com/questions/796607/how-do-i-override-tostring-in-c-sharp-enums) –
Fondamentalmente non correlato. La soluzione alla risposta in quel thread è già stata implementata in precedenza. Questa domanda sta andando molto oltre. – greggorob64