C#反射学习

前言:

此文章仅作本人学习笔记留存分享。如有出错欢迎指正。

反射(Reflection)的概念

.Net Framework 中提供了反射机制,可以再加载程序运行时,动态获取和加载程序集,并且可以获取到程序集的信息。 在程序集中,包含模块(Module),模块包含类型,类型包含成员,提供反射,我们可以查看到一个程序集的路径,命名空间,类。我们还可以对其进行操作。可以对程序集的类进行实例化,掉用类中的方法等,就跟我们普通使用程序集一样。

在Unity开发过程中,使用反射可以使代码更加灵活和可扩展,例如动态创建对象、动态调用方法和插件化开发等场景。

反射(Reflection)的用途

反射有下列用途:

  • 它允许在运行时查看特性(attribute)信息。
  • 它允许审查集合中的各种类型,以及实例化这些类型。
  • 它允许延迟绑定的方法和属性(property)。
  • 它允许在运行时创建新类型,然后使用这些类型执行一些任务。

优缺点

优点

  1. 动态加载和实例化对象:使用反射可以在运行时动态地加载和实例化对象,无需在编译时明确指定类型。这样可以提高代码的灵活性和可扩展性,使得代码更加适应变化和复杂性。

  2. 动态调用方法和属性:使用反射可以在运行时动态地调用对象的方法和属性,无需在编译时明确指定类型。这样可以使得代码更加适应变化和复杂性,同时也可以简化代码的编写。

  3. 插件化开发:使用反射可以实现插件化开发,即动态地加载和卸载插件。这样可以使得应用程序更加灵活和可扩展,同时也可以提高代码的复用性和可维护性。

缺点

  1. 性能开销:使用反射会带来一定的性能开销,因为需要在运行时进行类型信息的获取和转换。而且由于需要进行大量的类型检查和字符串匹配,所以在性能上会比直接调用类型和成员信息要慢。因此,在需要高性能的场景下,应尽量避免使用反射。

  2. 安全风险:由于反射可以在运行时动态地获取和调用类型和成员信息,所以在某些情况下可能会破坏代码的安全性。例如,可以使用反射来访问私有成员或者调用私有方法,这可能会导致代码的安全漏洞。因此,在使用反射时,需要特别注意代码的安全性。

  3. 代码可读性:使用反射会使代码的可读性变差,因为无法在编译时确定对象的类型和方法。如果使用不当,可能会导致代码难以理解和维护。

简单的使用场景

当我们需要动态地加载并实例化不同种类的角色。我们可以使用反射来实现这个功能。

using System;
using System.Reflection;

//基类
    public abstract class MyProgram {
        public string Actor { get; set; }
        public abstract void DisPlay();
    }
//派生类
    public class ProgramA: MyProgram {
        public override void DisPlay() {
            Console.WriteLine("ProgramA");
        }

        private void DisPlayPrivate() {
            Console.WriteLine("ProgramA DisPlayPrivate");
        }
    }
//派生类
    public class ProgramB : MyProgram {
        public override void DisPlay() {
            Console.WriteLine("ProgramB");
        }
    }
//派生类
    public class ProgramC : MyProgram {
        public override void DisPlay() {
            Console.WriteLine("ProgramC");
        }
    }


    //使用反射(Reflection)来动态地加载并实例化不同的类
    public class ProgramFactory {
        public MyProgram CreateProgram(string className) {
            Type type = Type.GetType(className);
            if (type == null) {
                Console.WriteLine("Cannot find class: " + className);
                return null;
            }

            object instance = Activator.CreateInstance(type);
            MyProgram character = instance as MyProgram;
            if (character == null) {
                Console.WriteLine("Invalid class type: " + className);
                return null;
            }

            return character;
        }
    }


    class Program {
        static void Main(string[] args) {
            Console.WriteLine("Use ProgramFactory");
            string dllName = "Reflection";

            //使用工厂
            ProgramFactory factory = new ProgramFactory();
            MyProgram programA = factory.CreateProgram($"{dllName}.ProgramA");
            programA.DisPlay(); // output: ProgramA

            MyProgram programB = factory.CreateProgram($"{dllName}.ProgramB");
            programB.DisPlay(); // output: ProgramB

            MyProgram programC = factory.CreateProgram($"{dllName}.ProgramC");
            programC.DisPlay(); // output: ProgramC


            //使用反射调用私有方法
            Type type = Type.GetType($"{dllName}.ProgramA");
            var ins = Activator.CreateInstance(type); //创建了一个ProgramA的实例
            MethodInfo method = type.GetMethod("DisPlayPrivate", BindingFlags.NonPublic | BindingFlags.Instance);//获取方法
            if (method != null) {
                method.Invoke(ins, new object[] { });//执行方法
            } else {
                Console.WriteLine("method is null");
            }
        }
    }  

//更多案例
//https://viehere.fun/2021/02/13/Csharp%E5%9F%BA%E7%A1%80%E2%80%94%E2%80%94%E5%8F%8D%E5%B0%84/#more
//

执行结果:

使用反射的工厂模式与传统的工厂模式相比具有以下的优点:

  1. 灵活性:传统的工厂模式需要在代码中显式地列出所有可能创建的对象类型,而动态工厂模式使用反射可以在运行时动态地加载并实例化对象,使得代码更加灵活和可扩展。
  2. 可读性:使用传统的工厂模式需要编写大量的if/else语句或者switch语句,用于判断要创建的对象类型,代码可读性不高。而动态工厂模式使用反射可以使代码更加简洁、易读。
  3. 维护性:传统的工厂模式需要在代码中显式地列出所有可能创建的对象类型,如果需要添加或删除一个新的对象类型,需要修改代码并重新编译。而动态工厂模式使用反射可以动态地加载并实例化对象,不需要修改代码并重新编译,使得维护更加方便。

但是,反射需要在运行时动态地获取类型信息,并且使用反射创建对象的速度比直接创建对象要慢。因此,在实际开发中,需要权衡使用反射带来的灵活性和性能开销,选择合适的方案。

学习资料:

C#超越菜鸟第十课:反射机制_哔哩哔哩_bilibili

C# 反射(Reflection) | 菜鸟教程

反射 Reflection | Witty

C#基础——反射 | ViE Here!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值