C# 反射调用方法与特性调用方法

在一些高级的开源项目中通常会使用到反射和打特性,如果对于c#初级的程序员第一眼看到肯定一脸懵逼,我以前也是这样过来的所以今天公司没啥事情可以干,就写一下笔记 ,unity 开源项目ET(以前看et项目时只知道原理不知其中的代码所以今天自已实现一下原理) 中就使用了这种方式实现。在此我解析一下反射与自定义特性的主要功能(反射网上搜索一大堆这里主要是介绍自定义特性的与反射结合使用的好处):

反射:反射就是通过加载程序集(什么是程序集,程序集就是一个文件,一个存放了IL语句的dll,它可以是C#所有的语法或者说一个项目中所有的cs文件,打包成IL语言,在此我们不学习IL语法只知道它是什么)获取类(class)再获取类中的属性、方法、字段;

所以下面主要实现的功能是 

例子 一:   通过反射调用方法

自定义 一个 类(可以是抽象类也可以是普通类)

//命名空间
namespace ConsoleApp1
{
//一个基类
  abstract  class Game
    {
        public virtual void start() { }
        public virtual void updata() { }
    }
//继承Game
    class Compent : Game
    {

       
        public  override void start() {
            Console.WriteLine("my  start");
        }
     
        public override void updata()
        {
            Console.WriteLine("updata");
        }
    }

}

然后在主线程中解析程序集调用方法

namespace ConsoleApp1
{ 
    class Program
    {

        //存放所有继承Game的子类
        private  static   List<Game> Games = new List<Game>();
        //是否退出
        private   static bool isexit = false;

        static void Main(string[] args)
        {

             //获取程序集所有的类
            Type[] types = typeof(Program).Assembly.GetTypes();

            //遍历
            foreach (Type  t in types) {

               // AttributeLogic(t);
                //如果是Game本身就下一条
                if (t.Name == typeof(Game).Name)
                    continue;
                //判断当前类是否继承Game
                if ( typeof(Game).IsAssignableFrom(t))
                {
                    //实例一个Game 子类
                    object reflectTest = Activator.CreateInstance(t);
                    Game g = reflectTest as Game;               
                    Games.Add(g);

                }                          
            }//找到了程序集所有继承Game的子类了并把它们都放在Games列表里边

            init();

            //结束主线程
            while (true)
            {
                if (Console.ReadKey().Key == ConsoleKey.A)
                {
                    isexit = true;
                   break;
                }
            }
        }

        //开始处理
        static void init()
        {

            foreach (var item in Games)
            {
                item.start();
            }

            new Thread(GameLogic).Start();
        }


        static void GameLogic()
        {
            while (!isexit)
            {
                foreach (var g in Games)
                {
                    g.updata();
                }
                Thread.Sleep(20);
            }
        }
            
    }
}

运行结果是

my start
updata
updata

 

简单的反射调用方法已经完成了。

例子二:自定义特性的与反射结合使用

首先我自定义自已的一个特性


namespace ConsoleApp1
{
    //自定义特性类
    [AttributeUsage(AttributeTargets.All)]
    class GameSystem:Attribute//正常格式是GameSystemAttribute这样的
    {
        public GameSystem() { }

    }

   //自定义一个player类
    class player
    {

        //GameSystem特性类的名字,如果定义的时候特性类的名字是这样GameSystemAttribute打上特性也是一样的
    
        [GameSystem]//给start打上特性
        public  void start()
        {
            Console.WriteLine("GameSystem  start");
        }


        [GameSystem]//也给updata打上特性
        public void Updata()
        {
            Console.WriteLine("my  updata");
        }
    }
}

 

然后在主线程中测试

 

namespace ConsoleApp1
{
    class Program
    { 
        static void Main(string[] args)
        {

          
            Type[] types = typeof(Program).Assembly.GetTypes();


            foreach (Type  t in types) {

                AttributeLogic(t);
            }
        }

        
        
        static void AttributeLogic(Type type)
        {
          
            
            foreach (MethodInfo method in type.GetMethods())
            {
                foreach (Attribute attr in method.GetCustomAttributes())
                {
                    if (attr is GameSystem)
                    {
                        object reflectTest = Activator.CreateInstance(type);
                        MethodInfo methodInfo = type.GetMethod(method.Name);
                        methodInfo.Invoke(reflectTest, null);
                    }
                }
            }

        }
        
    }
}

运行结果是

GameSystem start
my updata

这就是打特性的神其之处

只要你在任何方法中打上[GameSystem] 只要是无参的都可以任意执行(方法有返回值也可以),你也可以自已拓展方法中的参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值