• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
冥海
博客园    首页    新随笔    联系   管理    订阅  订阅

我看反射

1.什么是程序集
程序及其类型的数据都被称为元数据,保存在程序的程序集中。

2.在运行过程中检查和处理程序集中元素的功能。

3.Type类是发射的核心,也是进行发射的入口,当你获得了关于类型的Type对象后,就可以根据Type提供的属性和方法获取这个类型的一切信息。

4.获取一个类的类型
(1)使用Type类提供的静态方法GetType()
Type t = Type.GetType("System.IO.Stream");
(2)使用 typeof 操作符
Type t = typeof(System.IO.Stream);
(3)通过类型实例获得Type对象
String name = "Jimmy Zhang";
Type t = name.GetType();

(2)Type 提供了下面的属性,用于获取类型的基本信息,详情见图.

(3)如何进行程序集的加载
我们可以使用 Assembly类型提供的静态方法LoadFrom() 和 Load()
Assembly asm = Assembly.LoadFrom(@"d:\插件2Chinese.dll");

★★当使用LoadFrom()方法的时候,提供的是程序集的文件名,当将一个程序集添加到项目引用中以后,可以直接写“文件名.dll”。
Assembly asm2 = Assembly.Load("插件2Chinese"); //只用提供程序集名称即可,不能提供程序集的后缀名

第一步:应该是获取指定位置的程序集。
根据程序集创建程序集的类型。
把程序集的类型转换成为对象。
接口指向类对象
接口调用方法。


5.如何实现接口并利用接口调用方法
(1)本程序中引用的所有程序集
Assembly[] assm = AppDomain.CurrentDomain.GetAssemblies(); //程序域的当前应用程序域的程序集
foreach (Assembly assm1 in assm)
{
   Console.WriteLine(assm1.Location); //当前程序集的路径
}


(2)如何使用接口来进行反射
①创建一个接口的类库
public interface Icomputer  //定义为public是为了方便外界进行访问.
{
   void Say();
}

②创建一个实现接口的类库,★添加接口类库的引用★,类库中的类要实现这个接口
public class Person:Icomputer
{
        #region Icomputer 成员

        public void Say()
        {
            Console.WriteLine("您好啊");
        }

        #endregion
}

③主程序中添加对接口类库的引用


④加载实现这个接口的类的文件
string s = @"C:\Documents and Settings\Administrator\桌面\复习\发射\插件\bin\Debug\插件.dll";  //实现这个接口的类库所在的位置
Assembly assm = Assembly.LoadFile(s); //程序集中进行加载实现接口的类库


⑤获取程序集中当前实现接口的类库公共类型
Type[] type1 = assm.GetExportedTypes();
★★★由于实现接口的类库中有很多的类,所以要指定是哪一个类的类型。
Type types = type1[0];

⑥把当前类的类型转换成对象
object obj = Activator.CreateInstance(types);

⑦上述目的都是为了实现接口指向类的对象
Icomputer icom = obj as Icomputer;

⑧最终用接口进行方法的调用
icom.Say();


(3)对文件夹下所有的接口进行遍历
string[] files = Directory.GetFiles(@"c:\dll", "*.dll");
foreach (string file in files)
   {
      Assembly asm = Assembly.LoadFile(file);
      Type[] types = asm.GetExportedTypes();
      Type type = types[1]; //这个是哪个类文件的索引
      //获取类中定义的公共属性

      //对类中的所有属性进行遍历
      //PropertyInfo[] pro = type.GetProperties();
      //foreach (PropertyInfo pro1 in pro)
      //{
      //    Console.WriteLine(pro1);
      //}

      //访问指定的属性
      PropertyInfo[] pro = type.GetProperties();
      PropertyInfo pro1 = pro[0];
      Console.WriteLine(pro1);

      object obj = Activator.CreateInstance(type);//抽象类无法new

      Icomputer icom = obj as Icomputer;
      icom.Say();

  }

(4)获得类的类型
Type type1=typeof(Person); //获取指定类的类型
Type type2=p1.GetType();  //获取p1这个对象指向的的类型


(5)如何获得类中的所有属性
type.GetProperties()

//对类中的所有属性进行遍历
//PropertyInfo[] pro = type.GetProperties();
//foreach (PropertyInfo pro1 in pro)
//{
//    Console.WriteLine(pro1);
//}

//访问指定的属性
PropertyInfo[] pro = type.GetProperties();
PropertyInfo pro1 = pro[0];
Console.WriteLine(pro1);


(6)Activator.CreateInstance 必须是无参的构造函数,且是public


(7)两个类型进行指向,继承
Type typeicmd = typeof(IDbCommand);
Type typecmd=typeof(DbCommand);
Type typesqlcmd=typeof(SqlCommand);

//当前的实例是否可以指向实例 主 谓关系
Console.WriteLine(typeicmd.IsAssignableFrom(typecmd));
//判断当前类型是否是后面类型的子类
Console.WriteLine(typesqlcmd.IsSubclassOf(typecmd));


(8)如何给类型进行赋值
Type typep = typeof(Person); //获取类的类型

object obj1 = Activator.CreateInstance(typep);//把类型转换成对象

PropertyInfo proname = typep.GetProperty("name"); //通过类型获取属性
proname.SetValue(obj1, "zhangsan", null);//是哪个对象的属性

MethodInfo meth = typep.GetMethod("Say");
meth.Invoke(obj1, null); //调用方法,是哪个对象的方法
Console.ReadKey();


class Person
{
   public string name { get; set; }
   public int Age { get; set; }

   public void Say()
     {
      Console.WriteLine("说了一声{0}{1}", name, Age);
     }
}


★★★★★如何调用私有的方法   ★★★★★不到万不得已,最好别用
只要在方法调用的后面跟上 BindingFlags.NonPublic | BindingFlags.Instance
MethodInfo meth = typep.GetMethod("Say",BindingFlags.NonPublic | BindingFlags.Instance); //假设Say是一个私有的方法
meth.Invoke(obj1, null); //调用方法,是指调用哪个对象的方法


(8)制作一个可以动态根据dll进行的菜单栏
menuStrip1.Items.Add("工具");//最上面进行添加菜单栏
工具ToolStripMenuItem.DropDownItems.Add("测试");//添加菜单栏的下一级菜单栏


①在接口中声明一个只有返回值的get属性,和一个方法
public interface Icomputer
{
   string name { get;}
   string Exe(string oldtxt);

}
②声明一个实现接口的类,并且添加接口的引用
public class Computer:Icomputer
{
        #region Icomputer 成员

        public string name
        {
            get
            {
                return "转换为大写";
            }
        
        }

        public string Exe(string oldtxt)
        {
            return oldtxt.ToUpper();
        }

        #endregion
}

③在主程序中添加接口的引用

④加载实现接口的类文件,并且在程序集中获取该类的类型
string file = @"C:\Documents and Settings\Administrator\桌面\C#\动态加载菜单\实现接口\bin\Debug\实现接口.dll";
Assembly assm = Assembly.LoadFile(file);
Type[] type1 = assm.GetExportedTypes();

⑤对类型进行遍历,凡是实现了接口的类型,且不是抽象类的,就进行加载到窗体控件中。
foreach (Type types in type1)
{   //如果类型实现了接口,并且该类型不是抽象类型的话
    if (type2.IsAssignableFrom(types) && !types.IsAbstract)
       {   //接口指向实现了接口的对象
           Icomputer icom = (Icomputer)Activator.CreateInstance(types);
      
       //创建对应的菜单项
       ToolStripMenuItem tsm = new ToolStripMenuItem(icom.name);
       工具ToolStripMenuItem.DropDownItems.Add(tsm);
       tsm.Click+=new EventHandler(tsm_Click);
       tsm.Tag = icom;
       }
}


⑥写实现的具体代码
void tsm_Click(object sender, EventArgs e)
{
            ToolStripMenuItem mi = sender as ToolStripMenuItem;
            MessageBox.Show(mi.Text);
            Type plugintype = (Type)mi.Tag;
}


(9)如何对用户控件的属性进行标记
①对用户控件的属性进行标记的话,那么首先要声明一个属性
public string NameTel123
{
   get;
   set;
}

②在属性的上方标记[DisplayName("姓名电话")] 其中DisplayName是类DisplayNameAttribute的简写

(10)如何对用户控件的属性进行标记
Type type = telTextBox1.GetType(); //获取用户控件的类型
foreach (PropertyInfo prop in type.GetProperties())  //对类型的属性进行遍历
{
    if (!prop.CanRead) //如果该属性是只读的,那么退出本次循环,执行下一次循环
      continue;

    object propValue = prop.GetValue(telTextBox1, null); //把类型转换为对象

    //获得prop属性上标记的DisplayNameAttribute对象
   //因为可能标记多个,所以是数组
    object[] attributes =prop.GetCustomAttributes(typeof(DisplayNameAttribute), true);

    if (attributes.Length == 1)
    {
        DisplayNameAttribute dna = (DisplayNameAttribute)attributes[0];
        string displayname = dna.DisplayName;
        string text = string.Format("{0}={1}\r\n", displayname, propValue);
        textBox1.AppendText(text);
    }
   else
    {
        string text = string.Format("{0}={1}\r\n", prop.Name, propValue);
        textBox1.AppendText(text);
    }
}

posted @ 2011-04-18 11:01  冥海  阅读(303)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3