Overriding methods cannot be static: how else can I do what I'm trying to do?

I have a series of static classes that I use to get strings for enum values. They all look something like this:

public static class MyEnumToString
{
  private static Dictionary<MyEnum, string> map
   = new Dictionary<MyEnum, string>();

  public static string Get(MyEnum type)
  {
    PopulateEmptyMap();
    return map[type];
  }

  static void PopulateEmptyMap()
  {
    if (!map.Any())
    {
      PopulateMap();
    }
  }

  private static void PopulateMap()
  {
    map[MyEnum.enum1] = "string for enum 1";
    map[MyEnum.enum2] = "string for enum 2";
  }
}

I have several classes like this that differ in the type of Enum that they use and string values. Clearly, I have to combine classes to reduce duplicate code.

What I tried to do was create a common base class so that it can handle any type, and then implement the PopulationMap for the inherited classes. If it were possible, it would look something like this:

public static class TypeToString<TType>
{
  public static Dictionary<TType, string> map
   = new Dictionary<TType, string>();

  public static string Get(TType type)
  {
    PopulateEmptyMap();
    return map[type];
  }

  static void PopulateEmptyMap()
  {
    if (!map.Any())
    {
      PopulateMap();
    }
  }

  public abstract static void PopulateMap();
}

public static class MyEnumToString: TypeToString<MyEnum>
{
  public static void PopulateMap()
  {
    map[MyEnum.enum1] = "string for enum 1";
    map[MyEnum.enum2] = "string for enum 2";
  }
}

PopulationMap , , . , .

, , , " ", PopulateMap . , . , "PopulateMap" .

.

, , - ? TypeToString , TypeToString.Get().

+4
2

, , :

public static class EnumExtensions
{
    public static string GetDescription(this Enum value)
    {
        var field = value.GetType().GetField(value.ToString());
        if (field == null)
            return value.ToString();

        var attribute = field.GetCustomAttributes(typeof(DescriptionAttribute), false)
                             .OfType<DescriptionAttribute>()
                             .SingleOrDefault();

        return attribute != null
            ? attribute.Description
            : value.ToString();
    }
}

:

public enum Foo
{
    [Description("Hello")]
    Bar,

    [Description("World")]
    Baz
}

var value = Foo.Bar;
var description = value.GetDescription(); // Hello

, , GetDescription.


EDIT:, .

, - , :

[AttributeUsage(AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
public sealed class DescriptionEntryAttribute : Attribute
{
    public string Key { get; private set; }
    public string Value { get; private set; }

    public DescriptionEntryAttribute(string key, string value)
    {
        Key = key;
        Value = value;
    }
}

:

public enum Foo
{
    [DescriptionEntry("Name", "Hello")]
    [DescriptionEntry("Title", "Some title")]
    Bar,

    [DescriptionEntry("Name", "World")]
    [DescriptionEntry("Title", "Some title")]
    Baz
}

, , :

public static class EnumExtensions
{
    private static readonly ConcurrentDictionary<Type, DescriptionCache> Caches = new ConcurrentDictionary<Type, DescriptionCache>();

    public static string GetDescription(this Enum value, string key)
    {
        var enumType = value.GetType();
        var cache = Caches.GetOrAdd(enumType, type => new DescriptionCache(type));
        return cache.GetDescription(value, key);
    }

    public static IEnumerable<TEnum> GetValuesFromDescription<TEnum>(string key, string description)
        where TEnum : struct
    {
        var cache = Caches.GetOrAdd(typeof(TEnum), type => new DescriptionCache(type));
        return cache.GetValues(key, description).Select(value => (TEnum)(object)value);
    }

    private class DescriptionCache
    {
        private readonly ILookup<Enum, Tuple<string, string>> _items;
        private readonly ILookup<Tuple<string, string>, Enum> _reverse;

        public DescriptionCache(Type enumType)
        {
            if (!enumType.IsEnum)
                throw new ArgumentException("Not an enum");

            _items = (from value in Enum.GetValues(enumType).Cast<Enum>()
                      let field = enumType.GetField(value.ToString())
                      where field != null
                      from attribute in field.GetCustomAttributes(typeof (DescriptionEntryAttribute), false).OfType<DescriptionEntryAttribute>()
                      select new {value, key = attribute.Key, description = attribute.Value})
                .ToLookup(i => i.value, i => Tuple.Create(i.key, i.description));

            _reverse = (from grp in _items
                        from description in grp
                        select new {value = grp.Key, description})
                .ToLookup(i => i.description, i => i.value);
        }

        public string GetDescription(Enum value, string key)
        {
            var tuple = _items[value].FirstOrDefault(i => i.Item1 == key);
            return tuple != null ? tuple.Item2 : null;
        }

        public IEnumerable<Enum> GetValues(string key, string description)
        {
            return _reverse[Tuple.Create(key, description)];
        }
    }
}

:

  • Foo.Bar.GetDescription("Name") "Hello"
  • EnumExtensions.GetValuesFromDescription<Foo>("Title", "Some title") , Foo.Bar Foo.Baz

, , . , , , , .

+1

, . , , .

, , . , , :

  • PopulationMap:
  • :
  • :
  • , : Common

, , , , . , Lazy. , :

public abstract class TypeToString<Type>
{
    protected TypeToString()
    {
        storage = new Lazy<Dictionary<Type, string>>(GetMap);
    }
    private Lazy<Dictionary<Type, string>> storage;
    protected abstract Dictionary<Type, string> GetMap();
    public string Get(Type t) {return storage.Value[t];}
}
public class MyEnumToString : TypeToString<MyEnum>
{
    protected override Dictionary<MyEnum, string> GetMap()
    {
        return null;
    }
    public static Get(MyEnum e) { return new MyEnumToString.Get(e); }
}

[DescriptionAttribute], . , , . ( , , .)

+1

All Articles