Extension method on enumeration, not instance of enumeration

前端 未结 7 1077
耶瑟儿~
耶瑟儿~ 2020-11-29 04:28

I have an enumeration for my Things like so:

public enum Things
{
   OneThing,
   AnotherThing
}

I would like to write an extension method

相关标签:
7条回答
  • 2020-11-29 04:47

    Aaronaught's answer is really great, based on that I made the following implementation:

    public class SelectList
    {
        public static IEnumerable<Enum> Of<T>() where T : struct, IConvertible
        {
            Type t = typeof(T);
            if (t.IsEnum)
            {
                return Enum.GetValues(t).Cast<Enum>();
            }
            throw new ArgumentException("<T> must be an enumerated type.");
        }
    }
    

    In my opinion it's a little bit safer, as you can - almost - call it only with Enums, and of course instead of the throw you can simply return null if you want an exception-free version.

    0 讨论(0)
  • 2020-11-29 04:50

    In my opinion, this is the cleanest way. Why?

    • It works for any System.Enum
    • The extension method itself is cleaner.
    • To call it you just add new and that's a small trade off (because it has to have an instance in order to work.
    • You aren't passing null around and it literally won't compile if you try to use it with another type.

    Usage:

    (new Things()).ToSelectList()
    

    Extension Method:

    [Extension()]
    public SelectList ToSelectList(System.Enum source)
    {
        var values = from Enum e in Enum.GetValues(source.GetType)
                    select new { ID = e, Name = e.ToString() };
        return new SelectList(values, "Id", "Name");    
    }
    
    0 讨论(0)
  • 2020-11-29 04:59

    No.

    The best you can do is put it on a static class, like this:

    public static class ThingsUtils { 
        public static SelectList ToSelectList() { ... }
    }
    
    0 讨论(0)
  • 2020-11-29 05:00

    Extension methods only work on instances, so it can't be done, but with some well-chosen class/method names and generics, you can produce a result that looks just as good:

    public class SelectList
    {
        // Normal SelectList properties/methods go here
    
        public static SelectList Of<T>()
        {
            Type t = typeof(T);
            if (t.IsEnum)
            {
                var values = from Enum e in Enum.GetValues(type)
                             select new { ID = e, Name = e.ToString() };
                return new SelectList(values, "Id", "Name");
            }
            return null;
        }
    }
    

    Then you can get your select list like this:

    var list = SelectList.Of<Things>();
    

    IMO this reads a lot better than Things.ToSelectList().

    0 讨论(0)
  • 2020-11-29 05:01

    @Aaronaught has a very good answer. To extend his answer, you can also even make it more generic. I have this in a global library...

    public static IQueryable GetAllEnumValues<T>()
    {
        IQueryable retVal = null;
    
        Type targetType = typeof(T);
        if(targetType.IsEnum)
        {
            retVal = Enum.GetValues(targetType).AsQueryable();
        }
    
        return retVal;
    }
    

    Now you have de-coupled this functionality from the SelectList class. So you can call this in your SelectList methods, or anywhere else for that matter.

    public class SelectList
    {
        public static SelectList Of<T>
        {
            IQueryable enumValues = GetAllEnumValues<T>();
            var values = 
                from Enum e in enumValues
                select new { ID = e, Name = e.ToString() };
            return new SelectList(values, "Id", "Name");
        }
    }
    
    0 讨论(0)
  • 2020-11-29 05:08

    I use 'Type' instead of 'Enum' to add extension. Then I can get any type of list back from the method. Here it returns string values:

        public static string[] AllDescription(this Type enumType)
        {
            if (!enumType.IsEnum) return null;
    
            var list = new List<string>();
            var values = Enum.GetValues(enumType);
    
            foreach (var item in values)
            {
                // add any combination of information to list here:
                list.Add(string.Format("{0}", item));
    
                //this one gets the values from the [Description] Attribute that I usually use to fill drop downs
                //list.Add(((Enum) item).GetDescription());
            }
    
            return list.ToArray();
        }
    

    Later I could use this syntax to get what I want:

    var listOfThings = typeof (Things).AllDescription();
    
    0 讨论(0)
提交回复
热议问题