C# 通过枚举类型字符串,反射到枚举上

通过类型字符串,反射出任意类型

之前老顾写过一篇博客,通过反射,使用字符串,可以反射出当前项目中所有可用的类型,包括泛型类型。需要补课的小伙伴可以围观下老顾之前的文章《C# 根据typename字符串,创建任意类型的对象(含泛型)》。

虽然老顾自己也说了,使用这个方法,一般都是自己掉坑里的选择,不过确实有时候也会用到。

枚举类型

一般在自己开发的程序中,针对于特定的有限数据,我们一般会做出一个枚举类型,来规范所有参与项目的小伙伴,避免出现歧义或不规范内容。

比如,一个订单状态,根据业务流程,我们可以分成几个阶段:

提交未处理
已接收订单
待付款
已付款
待发货
正在配送
已配送完成
订单完成

等等这样的有限状态集合。
在这里插入图片描述
也比如说,访问网络资源,会返回一些状态码,比如 200、404、401、500 之类的,这些都是有限状态,所以通常我们都可以用 Enum 来定义一个枚举集合,规范一下数据。

这样的操作,主要是为了避免有的小伙伴写做待付款,有的小伙伴写做未付款,还有的写作待支付。。。总之,不用枚举规范的话,天知道会出现多少相同意义的数据。

CSDN 文盲老顾的博客https://blog.csdn.net/superwfei
老顾的个人社区https://bbs.csdn.net/forums/bfba6c5031e64c13aa7c60eebe858a5f?category=10003&typeId=3364713

通过反射调用枚举

大多数时候,我们在使用枚举的时候,都是明确知道其类型的,所以,我们通常是直接用 Enum.GetName(枚举类型,值) 的方式来获取对应的文本描述。

但是,偶尔,我们需要调用枚举的位置,并不是我们手写的代码,而是类似模版定义这样的内容,比如,现在老顾就有这么一个模板定义:

404.enum.httpstate

404 是值,enum 是调用枚举,httpstate 是枚举类型

正常在程序里写的话,那么就应该是这样了

Enum.GetName(httpstate,404)

但是模版里的话。。。这个 httpstate 是可以解析了,但如果有多个模版,且枚举类型不一致呢?

比如,有这么个模板内容:

html symbols: ^lt,enum,htmlsymbols^ ^trage,enum,htmlsymbols^ ^gt,enum,htmlsymbols^
http state: ^200.enum.httpstate^ ^403.enum.httpstate^ ^500.enum.httpstate^ 
bidstate: ^11.enum.trade^ ^91.enum.trade^ ^99.enum.trade^

那么,这里出现了三个枚举类型,如果少的话,不通过反射,用程序一个一个分支,或者 switch 一下,也是可以的,但是,如果再出现新的类型,那么还是很痛苦的,经常需要改代码了。

所以,我们还是通过反射来实现枚举调用。

GetTypeByName(EnumName) 为空?

我们直接使用之前定义的通过类名字符串调用类的方法 GetTypeByName,里面的参数给一个枚举类型。。。结果。。。没有能获取到枚举类型?Type 返回的是 null ??

我连泛型都搞出来了,你告诉我,枚举不能用?

                        foreach (Type st in ts)
                        {
    
    
                            if (RegexExpand.IsMatch(st.FullName, @"\." + RegexExpand.FormatRegExp(source) + @"(`?\d+)?$"))
                            {
    
    
                                return st;
                            }
                        }

打开原来的代码,在 RegexExpand.IsMatch 这一行,老顾打了一个断点,然后,发现枚举Enum 的字符串类型。。。有点哭笑不得。

在这里插入图片描述
好么,类的话,FullName 就是 xxx.yyy.zzz 的方式,泛型就是 xxx.yyy.zzz`n 的方式,结果,枚举类型,你给来了个 xxx.yyy+zzz 的方式。。。。

所以,修改起来也非常简单,把刚才代码中的正则 @“\.” 换成 @“[\.+]” 即可。

然后,我们就可以正常的调用枚举处理内容了:

                        try
                        {
    
    
                            Type t = Common.GetTypeByName(枚举类型字符串);
                            return Enum.GetName(t, int.Parse(枚举值));
                        }
                        catch (Exception ex)
                        {
    
    
                            return ex.Message;
                        }

小结

好吧,没什么可多总结的,就是 FullName 的格式,有点出乎预料,也许,还有其他形式的FullName。总之,还是要多见识见识才好。

另外,再补充一下,直接把 RegexExpand 修改成 Regex 即可,这是老顾自己定义的一个静态类,继承并扩充了一下 Regex 罢了。

FormatRegExp 方法,就是将字符串转成正则表达式,类似 py 中的 re.escape

        public static string FormatRegExp(string str)
        {
    
    
            return str.Replace("\\", @"\\").Replace("(", "\\(").Replace(")", "\\)").Replace("{", "\\{").Replace("}", "\\}").Replace("[", "\\[").Replace("]", "\\]").Replace(".", "\\.").Replace("+", "\\+").Replace("-", "\\-").Replace("^", "\\^").Replace("$", "\\$").Replace("?", "\\?").Replace("*", "\\*").Replace("|", "\\|");
        }

其实,就是几个字符替换的事,自己随便放到哪里都可以。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/superwfei/article/details/131834273
今日推荐