关于C#的反射,你真的运用自如嘛?

前言

咱们都知道反射在编程语言里是很是方便也是很是强大的,但或许有人会以为在学习或者工做中用的可能并非那么多,这对于刚入行不久的人而言的,个人理解是反射在写框架和写工具是用的比较多的。举个栗子:写一个Excel的表格编辑器,咱们可以在控制台修改Excel里面的内容,或许有人会以为这有啥难的,直接手撸对应的Model,若是哪一天策划手滑或者手贱修改了命名,或者增长/减小一列,那咱们程序是否是也要跟着修改,由于咱们保存数据或许是写死的字段名,若是所有经过反射,那就随便策划怎么折腾excel,我有反射神器,我不怕!至于为啥要写Excel的编辑器,或许有人会疑惑,我直接在Excel里面编辑修改不行嘛,这样策划要修改个数据而后要导出数据,而后在游戏里面跑,会比较麻烦,若是有对应的表格编辑器直接在游戏运行时就修改测试就很方便,若是是bool类型就给策划toggle选项,若是是枚举类型就弄个下拉框,若是是范围类型就给个Range,这样策划就不会填错,若是编辑器是基于反射作的,不是字段写死的,策划随便修改excel的字段都不会出问题。html

反射获取属性

typeof(Animal).GetProperties()

反射获取/设置属性的值

获取值web

properities[i].GetValue(a)

获取的值是object类型的,若是想要转成对应真实类型,而后调用对应类型的扩展方法能够经过if去一个个判断而后强转,还没想到特别方便的通用的转换方式,也有看到过Convert.ChangeType,但返回类型仍是Object,不是我想要的,若是有人知道有更好的方式,还请留言告知。编程

设置值api

properities[i].SetValue(a, object xxx)

反射调用字段的扩展方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace ConsoleApp1
{
    public class Animal
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public static class Extension
    {
        public static string GetStringValue(this int v)
        {
            return "我是Int类型:" + v;
        }

        public static string GetStringValue(this string v)
        {
            return "我是String类型:" + v;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Animal a = new Animal() { ID = 1, Name = "mimi" };

            var properities = typeof(Animal).GetProperties();
            var thisassembly = typeof(Animal).Assembly;
            for (int i = 0; i < properities.Length; i++)
            {
                var v = properities[i].GetValue(a);
                foreach (var m in GetExtensionMethods(thisassembly, v.GetType()))
                {
                    var vv = m.Invoke(null, new object[] { v });
                    Console.WriteLine(vv);
                }
            }

            Console.Read();
        }


        //反射获取扩展方法
        static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,
       Type extendedType)
        {
            var query = from type in assembly.GetTypes()
                        where type.IsSealed && !type.IsGenericType && !type.IsNested
                        from method in type.GetMethods(BindingFlags.Static
                            | BindingFlags.Public | BindingFlags.NonPublic)
                        where method.IsDefined(typeof(ExtensionAttribute), false)
                        where method.GetParameters()[0].ParameterType == extendedType
                        select method;
            return query;
        }

    }
}

在这里插入图片描述
我在一开始没用上述反射获取扩展方法时,直接用的xxx.GetType().GetMethod(“GetStringValue”)是获取不到这个扩展方法的,在这里插入图片描述
至于为啥普通方式获取不到扩展方法,这个要看IL层的设计了,事实上一个类的扩展方法并不属于该类,而是属于定义他的静态类,之因此可以调用,是由于编译器作了手脚的缘故,编译器遇到这种情况就会调用静态类的方法,经过其IL就能够看到真实的调用状况。sass

更多反射相关的API

仍是参考官方文档最丰富呀。
https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.propertyinfo?view=netframework-4.8#属性框架

参考连接

https://codeday.me/bug/20170729/42358.html编程语言

更多文章

http://dingxiaowei.cn/编辑器