C# 反射-通过继承接口实现创建对象并调用方法

初学反射,在个人理解中,他的主要目的是为了让系统实现可扩展 可配置。

反射+配置文件+工厂 为例

先来一个接口类

 public interface IShowFun
    {
        void Say();
        void Do();
    }


一个集成该接口的方法
 public class ShowGirlFun:IShowFun
    {
        public void Say()
        {
            Console.WriteLine("我是女生");
        }


        public void Do()
        {
            Console.WriteLine("我要穿裙子");
        }
    }

通过配置文件 记录 该方法的命名空间 和类全名

<appSettings>       <add  key="ShowGirlFun" value="ShowGirl,ShowGirl.ShowGirlFun"/>  </appSettings>

设置一个工厂,读取配置文件,通过反射 创建并返回一个IShowFun对象

这里需要注意的是,如果用到读取配置文件 需要添加System.Configuration;引用

 public class Factory
    {
        private static string txt = ConfigurationManager.AppSettings["ShowGirlFun"];

        public static IShowFun CreateInstance()        
        {
           
            string nametxt=txt.Split(',')[0];
            string funtxt=txt.Split(',')[1];
            Assembly assembly=Assembly.Load(nametxt);
            Type type=assembly.GetType(funtxt);
            return (IShowFun)Activator.CreateInstance(type);
        }
    }

调用代码

 IShowFun fun = Factory.CreateInstance();
            fun.Say();
            fun.Do();
结果:



上面情况是在不需要调用方引用ShowGirlFun的类库的情况下,只需要将ShowGirlFun类库下面的dll拷贝到调用方的bin/Debug文件夹下


下面 ,如果我想修改一下,改成男生,只需要再新建一个男生的类库 然后继承IShowFun接口并实现,然后把男生单独生成的dll拷贝到调用方的bin/Debug下面,修改一下bin/Debug/?*.exe.config中的配置文件 即可

如下

添加一个男生

public class ShowBoyFun:IShowFun
    {
        public void Say()
        {
            Console.WriteLine("我是男生");
        }


        public void Do()
        {
            Console.WriteLine("我要穿裤子");
        }
    }


将它生成并将dll拷贝到调用方的bin/Debug下面

然后修改bin/Debug/?*.exe.config中的配置文件 

<add  key="ShowGirlFun" value="ShowGirl,ShowGirl.ShowGirlFun"/>
改成

<add  key="ShowGirlFun" value="ShowBoy,ShowBoy.ShowBoyFun"/>
之后 运行exe程序 会发现发生了变化



多参数构造函数调用

创建构造参数为有参数的,只需要在创建的时候,按照先后顺序,把参数写进去就可以了,如下

 Assembly assembly=Assembly.Load(nametxt);
            Type type=assembly.GetType(funtxt);
            return (IShowFun)Activator.CreateInstance(type,"啊啊啊",11);
这样 就创建了一个 有2个参数,分别是string和int的构造函数,他会根据参数的类型和数量,自动去匹配相对应的构造函数


破坏单例

反射可以突破访问限制,直接调用私有构造函数

比如现在做一个单例模式

 public class Singleton
    {
         private Singleton()
         {
             Console.WriteLine("构造函数被运行一次");
         }

         private static Singleton singleton = new Singleton();

         public Singleton CreateInstance()
         {
             return singleton;
         }
    }

通过反射进行调用

Console.WriteLine("********************破坏单例**********************");
                Assembly assembly = Assembly.Load("DoSomeThing");//引用dll
                Type type = assembly.GetType("DoSomeThing.Singleton");
                Activator.CreateInstance(type, true);
                Activator.CreateInstance(type, true);
                Activator.CreateInstance(type, true);
                Activator.CreateInstance(type, true);
结果


结果可以看到,即使是单例下的私有构造函数,也被调用了很多次


泛型构造函数调用

我们先创建一个泛型类

 public class GenericClass<T,S>
    {
        public GenericClass()
        { 
            Console.WriteLine("GenericClass");
        }

    }

调用

  Console.WriteLine("********************创建泛型类对象**********************");
                Assembly assembly = Assembly.Load("DoSomeThing");
                Type type = assembly.GetType("DoSomeThing.GenericClass`2");
                type = type.MakeGenericType(typeof(string),typeof(int));
                Activator.CreateInstance(type);
结果



看结果是创建成功的,创建泛型类对象的时候,其实就是在创建类型的时候,在类型名称后面加上一个 `N  这个N就是代表有几个泛型参数,然后通过MakeGenericType进行添加泛型类型即可

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值