动态生成时自定义c# Enum ToString()

本文关键字:Enum ToString 自定义 动态 | 更新日期: 2023-09-27 18:11:09

我在c# ASP中从数据库生成表示整数id的动态枚举。网络解决方案。我想要两样东西,虽然两者都不可能。

1)我希望。tostring()方法给我"345",例如,不是枚举的字符串名称(它表示为字符串的int)。这个问题的每个答案似乎都在增加

[Description="Blah"]
EnumName = 1

声明之上,并使用GetDescription()方法。我不知道如何用我正在使用的动态代码做到这一点。

2)我宁愿不强制转换为int来使用它,我宁愿(Enum)。Name == 5)为例。如果这是不可能的,我将强制转换,但我真的不想使用((int)Enum.Name)).ToString();

下面是动态代码生成:

public static void Main()
{
    AppDomain domain = AppDomain.CurrentDomain;
    AssemblyName aName = new AssemblyName("DynamicEnums");
    AssemblyBuilder ab = domain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save);
    ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
    List<Type> types = new List<Type>();
    foreach(ReferenceType rt in GetTypes())
    {
        EnumBuilder eb = mb.DefineEnum(rt.Name, TypeAttributes.Public, typeof(int));
        foreach (Reference r in GetReferences(rt.ID))
        {
            eb.DefineLiteral(NameFix(r.Name), r.ID);
        }
        types.Add(eb.CreateType());
    }
    ab.Save(aName.Name + ".dll");
    foreach (Type t in types)
    {
        foreach (object o in Enum.GetValues(t))
        {
            Console.WriteLine("{0}.{1} = {2}", t, o, ((int) o));
        }
        Console.WriteLine();
        //Console.ReadKey();
    }
    Console.WriteLine();
    Console.WriteLine("Dynamic Enums Built Successfully.");
}
public static string NameFix(string name)
{
    //Strip all non alphanumeric characters
    string r = Regex.Replace(name, @"[^'w]", "");
    //Enums cannot begin with a number
    if (Regex.IsMatch(r, @"^'d"))
        r = "N" + r;
    return r;
}

可能没有办法做我想做的事情,我将被困在使用:

(int)Countries.USA //For int value
((int)Countries.CAN).ToString() //For string representation of int value, ex. "354"

任何想法?

动态生成时自定义c# Enum ToString()

你能适应类型安全的枚举模式来做你需要的吗?

public class MyEnum
{
    #region Enum Values
    // Pre defined values.    
    public static readonly MyEnum ValueOne = new MyEnum(0);
    public static readonly MyEnum ValueTwo = new MyEnum(1);
    // All values in existence.
    private static readonly Dictionary<int, MyEnum> existingEnums = new Dictionary<int, MyEnum>{{ValueOne.Value, ValueOne}, {ValueTwo.Value, ValueTwo}};
    #endregion
    #region Enum Functionality
    private readonly int Value;
    private MyEnum(int value)
    {
        Value = value;
    }
    public static MyEnum GetEnum(int value)
    {
        // You will probably want to make this thread-safe.
        if (!existingEnums.ContainsKey(value)) existingEnums[value] = new MyEnum(value);
        return existingEnums[value];
    }
    public override string ToString()
    {
        return Value.ToString();
    }
    #endregion
}

用法:

private void Foo(MyEnum enumVal)
{
  return "Enum Value: " + enumVal;  // returns "Enum Value: (integer here) 
}

或:

MyEnum.GetValue(2) == MyEnum.GetValue(4); // false
MyEnum.GetValue(3) == MyEnum.GetValue(3); // true

所以您实际上想将Enum值转换为string而不是名称?转换为Enum的底层类型是获取值的最简单方法。我认为你很难找到比((int)...)更短或更简单的东西。

如果你不想"枚举"一些值,或者想做一些不同的事情,你可以创建自己的YourEnum类,它基本上内置了强制转换,在需要时强制转换似乎更容易,更可读。

也许你真的需要一些常量。

const string Blah = "345";

编辑

我有另一个想法,你可以为Enum写一个扩展方法,像这样,

public static class MyExtentions
{
    public static string ValueString(this Enum e)
    {
       var ut = Enum.GetUnderlyingType(e.GetType());
       var castToString = typeOf(MyExtentions).GetMethod("CastToString");
       var gcast = cast.MakeGenericMethod(ut);
       var gparams = new object[] {e};
       return gcast.Invoke(null, gparams).ToString();
    }
    public static string CastToString<T>(object o)
    {
        return ((T)o).ToString();
    }

}

有了这个,你可以在任何Enum实例上调用ValueString()并获得值的字符串。它显然使用了反射,所以性能不会很惊人,但我认为这对你来说无关紧要。

当您使用Enum类类型时,使用Enum如何?格式方法。

例如:

enum EnumClassA {One, Two, Three, Four};
...
EnumClassA chosenValue = EnumClassA.Three;
Console.WriteLine("Chosen value is {0}", Enum.Format(typeof(EnumClassA), chosenValue, "d"));

这应该给出如下输出:

Chosen value is 2

编辑

另一个选项是:

EnumClassA.Three.ToString("d"); //Enum.Name.ToString("d")

这也给出了一个字符串值"2"。

** edit **

当你做比较看值是否存在于你的枚举中,如何使用Enum。IsDefined(enumType, value)返回bool值?

Console.WriteLine("Does the enumClassA contain {0} result is {1}", 5, Enum.IsDefined(typeof(enumClassA), 5));

输出如下:

Does the enumClassA contain 5 result is False

我意识到问题已被标记为回答,但也许使用扩展可能是有用的?

它仍然允许您以这种方式使用生成的枚举。

p。在调用GetString时要小心——不要不小心调用ToString !

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
namespace ConsoleApplication1
{
    public enum YourEnum
    {
        Apples = 1,
        Pears = 2,
    }
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var value in (YourEnum[])Enum.GetValues(typeof(YourEnum)))
            {
                int v = value.GetValue();
                Console.WriteLine("{0} = {1} (int)", value.ToString(), v);
                string s = value.GetString();
                Console.WriteLine("{0} = {1} (string)", value.ToString(), s);
            }
            Console.ReadLine();
            //Results:
            //Apples = 1 (int)
            //Apples = 1 (string)
            //Pears = 2 (int)
            //Pears = 2 (string)
        }
    }
    public static class EnumExtensions
    {
        public static int GetValue(this Enum value) 
        {
            return Convert.ToInt32(value);
        }
        public static string GetString(this Enum value)
        {
            return Convert.ToInt32(value).ToString();
        }
    }
}