zoukankan      html  css  js  c++  java
  • 认识反射

    先看段代码:

    Interface IMedia

    {

       Void Play();

       Void Stop();

    }

    Public class Radio : IMedia

    {

    Void Play();{….}

       Void Stop();{….}

    }

    Public class Recorder;: IMedia

    {

    Void Play();{….}

       Void Stop();{….}

    }

    Public class MediaFactory

    {

           //取得所有播放设备

           Public string[] GetDevicelst() {return new string[]{“Radio”,” Recorder”};

           Public IMedia CreateDevice(string DeviceName)

           {

                  If (DeviceName== “Radio”)

                         rturn new Radio();

                  else if  (DeviceName== “Recorder”)

                         rturn new Recorder ();

                  elser

                         return null;

           }

    }

    可见页面:

    这段代码想必都很熟悉,这就不是个工厂模式么,没错,是个典型的工厂模式,而且还知道不少优点:

    1.        采用了接口方式,统一使用IMedia来调用,而不会直接使用RadioRecorder,省了不少代码,不再需要很多重复代码了;

    2.        可以方便的扩展啊,比如我再新增一种播放设备的话,只要新增一个类,然后在MediaFactory中加上相应的代码就可以了啊,这对于使用者来说,可以不用修改代码了。

    方便,确实方便很多了,但仔细想来啊,又有麻烦了,前面的程序已经开发好了,我要再加一个播放设备,加一个类的话,还得打开原先的代码,加上这个类,然后再MediaFactory中加上创建便个新类的方法,然后再编译后才能使用。

     

    能不能简化呢,能不能我这个新的播放类,单独写一下,放到一个新的dll中,然后把这个dll往原先的exe目录中一放,然后就可以调用到这个新的播放类呢,这样我就可以不动原先的程序了呢?

    答案是可以的:

           Public string[] GetDevicelst() {return new string[]{“Radio”,” Recorder”};

    看到这段代码,我们想到了,这个字符串不就可以保存在配置文件中吧,好,改之:

           Public string[] GetDevicelst() {return Settings.Devicelist.Split(‘;’);}

    在配置文件(exe.config)中:

    <userSettings>

            <WindowsFormsApplication1.Properties.Settings>

                <setting name=" Devicelist " serializeAs="String">

                    <value> Radio ; Recorder </value>

                </setting>

            </WindowsFormsApplication1.Properties.Settings>

        </userSettings>

    好,取得设备列表的动态生成搞定了,新增一个类,也只要在这个配置文件里面加个,但看第二个方法CreateDevice,犯难了,在配置文件里面我保存的是类名的字符串,而在这个方法里面得返回其实例,得用new 类名()来创建对象。

    这里我们在想是不是有这样一个方法,object instance = CreateInstance(“类名”),这样通过一个字符串,系统就给我返回相应的对象实例。

    答案是有的,有这样的方法,这就是反射,我们看下怎么来用。

    我们知道,在C#里面类型是随便取的,也就是就可以让两个类型相同,只不过在同一个程序里面,这两个相同的类得用不同的命空间里,在同一程序里,要表达一个类,得用命名空间.类名来表示。

    但是在不同的dll中,还是会出现相同的命名空间和类名,所以对于全局来讲,要唯一表过一个类的话,得这样写命名空间.类名,程序集名。一般来说,这要样肯定也就够了,但时,不难保证,我的dll名称也可能相同啊,哦好,加个版本吧:命名空间.类名,程序集名, Version=版本号,那对于.net来说,还有一个多国语言支持呢,我同一批程序同一个版本,不同国家语言的包也可以相同啊,哦好,再加个语言限定吧:命名空间.类名,程序集名, Version=版本号, Culture=neutral这里面的neutral表示本地化的,就是自动读取操作系统的语言。如果再有相同的怎么办呢,没关系,我们可以在这个程序集上加一个guid啊,这个叫做强签名,这样,这个dll中的类就完全唯一了:命名空间.类名,程序集名, Version=版本号, Culture=neutral, PublicKeyToken=null/Guid值。OK,这就是一个类的全名的表示法,当然可以简写,命名空间.类名,程序集名,只要系统中没发现重复的就没事,发现重复的就要报错了的哦。

    既然每个类可以用这个长长的字符串来定义的话,在framework中,就有这样一个表示类的类,叫做Type,每一个Type实例都唯一对应着一个类,那么Type对象怎么获取呢,肯定只有在dll(程序集)中找咯,又有一个对象Assembly,这个类是专门来表示程序集的,在这个Assembly中,有一个方法GetTypes,返回这个dll中的所有Type的集合。有了Type对象后就可很方便地创建其实例咯:

    Assembly  assembly = Assembly.LoadFile("xxxx.dll");

    Type  type = assembly.GetType("Radio");

    object instance = Activator.CreateInstance(type);  //创建实例

    IMedia media = instance as IMedia;                   

    这下好办了,可以能过字符串来取得对象了,好,将前面的代码改造下,连原来的配置文件都不要了:

    Public class MediaFactory

    {

           //取得所有播放设备, hash表记录所有的设备列表,<名称,类型>

           Public Hashtable GetDevicelst() {

                       Hashtable rtn = new Hashtable();

                  foreach (string file in Directory.GetFiles(Application.ExecutablePath, "*.dll"))

    {

                     Assembly assembly = Assembly.LoadFile("xxxx.dll");

                     foreach (Type type in assembly.GetTypes())

                     {

                        //判断type是否继承IMedia

                        rtn.Add(type.Name, typ)

                     }

              }

              return rtn;

    }

     

           public IMedia CreateDevice(Type type)

           {

                  Type  type = assembly.GetType("Radio");

                  object instance = Activator.CreateInstance(type);  //创建实例

                  return  instance as IMedia;

           }

    }

    看明白这段代码了吧,这样就实现了前面的要求,丢个dllexe下面,就可以认出里面的IMedia类来并可调用了。

     

    既然可以通过字符串来找到程序集,找到里面的类,还能创建具体的实例,那能不能继续,查找到类里有几个函数,有几个属性,然后能否再动态取得你这们实例里面的某个属性值,动态调用类里面的方法呢:

                  type.GetProperties();

                  type.GetMethods();

                  PropertyInfo prop;

                  prop.GetValue(obj);

                  MethodInfo method;

                  method.Invoke(obj, 参数);

    看吧,这些方法够你遐想了,尽情地用到你可以简化代码的地方法吧!

    反射,在类里面,反过来动态(运行时)找找类本身内部有哪些方法属性等结构!

  • 相关阅读:
    PHP 大文件上传方法(500M以上)
    PHP 大文件上传思路(500M以上)
    PHP 大文件上传功能(500M以上)
    PHP 大文件上传方案(500M以上)
    PHP 大文件上传技术(500M以上)
    PHP 大文件上传实例解析(500M以上)
    PHP 大文件上传示例(500M以上)
    PHP 大文件上传实例(500M以上)
    支持复制粘贴word公式的百度编辑器
    支持复制粘贴word公式的HTML编辑器
  • 原文地址:https://www.cnblogs.com/zjfstudio/p/3764717.html
Copyright © 2011-2022 走看看