zoukankan      html  css  js  c++  java
  • C#2008与.NET 3.5 高级程序设计读书笔记(16) 类型反射、晚期绑定和基于特性的编程

    1.反射

    在.NET中,反射(reflection)是一个运行库类型发现的过程.通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。

    (1)命名空间

    (2)一些在发射中经常用到的类

    Assembly

    Assembly类是可重用、无版本冲突并且可自我描述的公共语言运行库应用程序构造块。可以使用Assembly.LoadAssembly.LoadFrom方法动态地加载程序集。

    Type

    反射的中心是System.Type类。System.Type类是一个抽象类,代表公用类型系统中的一种类型。这个类使您能够查询类型名、类型中包含的模块和名称空间、以及该类型是一个数值类型还是一个引用类型。

    System.Type类使您能够查询几乎所有与类型相关的属性,包括类型访问限定符、类型是否、类型的COM属性等等。

    获取给定类型的Type引用有3种常用方式:
        ●使用 C# typeof 运算符。
            Type t = typeof(string);
        ●使用对象GetType()方法。
            string s = "grayworm";
            Type t = s.GetType();
        ●还可以调用Type类的静态方法GetType()。
            Type t = Type.GetType("System.String");

    Activator

    Activator类支持动态创建.NET程序集和COM对象。可以通过CreateComInstanceFromCreateInstanceCreateInstanceFromGetObject四个静态方法加载COM对象或者程序集,并能创建指定类型的实例。

    Binder

    Binder类是一个用于执行类型转换的绑定器,Type对象的InvokeMember方法接受Binder对象,这个对象描述了如何将传递给InvokeMember的参数转换成方法实际需要的类型。

    Binder类是一个抽象类,要创建绑定器,需要重写方法BindToMethodBindToFieldSelectMehtodSelectPropertyChangeType

    DefaultMemberAttribute

        DefaultMemberAttribute类用于类型并带有一个指明默认成员名称的字符串参数。能够通过InvokeMember调用默认成员,而不需要传递调用成员的名称。当需要绑定器但不需要特别的绑定行为时就可以使用它。

    其它

    还有一些对元素类型信息描述的类,ConstrutorInfo(构造函数)、MethodInfo(方法)、FieldInfo(字段)、PropertyInfo(属性)、EventInfo(事件)、MemberInfo(成员)、ParameterInfo(参数)。如果查询得到了具有任何类型信息的实例,就可以获得该类型中任意元素的类型信息,当然出于安全原因,不保证会得到程序集中的任何信息。

    例子:

    首先我们先建立一个类库工程MyDll,并新建一个类ReflectTest

    代码
    using System;

    namespace MyDll
    {
    /**//// <summary>
    /// ReflectTest 的摘要说明。
    /// </summary>

    //接口
    public interface ITest
    {
    int add();

    }

    public class ReflectTest : ITest
    {
    public String Write;
    private String Writec;

    public int add()
    {
    return 10;
    }

    public String Writea
    {
    get { return Write;}
    set { Write = value;}
    }

    private String Writeb
    {
    get { return Writec;}
    set { Writec = value;}
    }

    //构造函数
    public ReflectTest()
    {
    this.Write = "Write";
    this.Writec = "Writec";
    }

    //有参构造函数
    public ReflectTest(string str1,string str2)
    {
    this.Write = str1;
    this.Writec = str2;
    }

    public string PrintString(string s)
    {
    return "这是一个实例方法" + s;
    }

    private string PrintString2()
    {
    return "这是一个私有方法";
    }

    public static string Print(string s)
    {
    return "这是一个静态方法," + s;
    }

    public string PrintNoPara()
    {
    return "您使用的是无参数方法";
    }

    public static string PrintData(string s)
    {
    return s;
    }

    public static string PrintData(string s1, string s2)
    {
    return s1+s2;
    }



    }
    }

    编译后得到MyDll.dll文件,应用反射

    代码
    using System;
    using System.Reflection;

    namespace cmdText
    {
    /**//// <summary>
    /// 说明:反射学习
    /// 程序:寻梦E.net
    /// </summary>
    public class Reflect2
    {

    delegate string TestDelegate(string value1);

    public static void Main(string[] args)
    {
    Assembly ass
    = null ;
    Type type
    = null ;
    object obj = null;

    string assemblyName = "MyDll";
    string className = "MyDll.ReflectTest";

    try
    {
    //以下三种方法都可以
    //ass = Assembly.LoadFile(System.Environment.CurrentDirectory+"/MyDll.dll");
    //ass = Assembly.LoadFrom(System.Environment.CurrentDirectory+"/MyDll.dll");
    ass = Assembly.Load(assemblyName);

    }
    catch
    {
    Console.Write(
    "无法找到程序集!");
    return;

    }
    //获取类型
    type = ass.GetType(className);
    //type = Type.GetType(className);//效果同上
    //生成一个类实例,无参构造函数
    obj = ass.CreateInstance(className);
    //obj = Activator.CreateInstance(type);//效果同上


    //**************************方法调用*************************************
    //反射实例方法

    Console.WriteLine(
    "*******方法调用**************************************");
    MethodInfo method
    = type.GetMethod("PrintString");
    string s = (string)method.Invoke(obj,new string[]{"寻梦E.net"});
    Console.WriteLine(s);

    //反射私有方法
    method = type.GetMethod("PrintString2",BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
    s
    = (string)method.Invoke(obj,null);
    Console.WriteLine(s);

    //反射静态方法
    method = type.GetMethod("Print");
    s
    = (string)method.Invoke(null,new string[]{"寻梦E.net"});
    Console.WriteLine(s);

    //反射无参方法
    method = type.GetMethod("PrintNoPara");
    s
    = (string)method.Invoke(obj,null);
    Console.WriteLine(s);

    //反射重载了的静态方法
    Type[] objParam = {typeof(string),typeof(string)};
    method
    = type.GetMethod("PrintData",objParam );
    s
    = (string)method.Invoke(null,new object[]{"hello!"," 寻梦E.net"});
    Console.WriteLine(s);

    Console.WriteLine(
    "*******属性,域的赋值与访问***********************");


    //*****************属性,域的赋值与访问***************************************
    //公有属性
    PropertyInfo pi1 = type.GetProperty("Writea");
    pi1.SetValue(obj,
    "公有属性:Writea", null);
    Console.WriteLine(pi1.GetValue(obj,
    null));

    //私有属性
    PropertyInfo pi2 = type.GetProperty("Writeb", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
    pi2.SetValue(obj,
    "私有属性:Writeb", null);
    Console.WriteLine(pi2.GetValue(obj,
    null));

    //
    FieldInfo fi1 = type.GetField("Write");
    Console.WriteLine(fi1.GetValue(obj));


    Console.WriteLine(
    "*******类型,模块,方法,构造函数等信息的获取*****");




    //******************类型,模块,方法,构造函数等信息的获取******************************************

    //有参构造函数实例化
    //string[] classParams = {"lsm","sky"};
    //object obj2 = Activator.CreateInstance(type,classParams);

    foreach(Type t in ass.GetTypes())
    {
    Console.WriteLine(
    "类型:"+t.Name );
    }

    foreach(Module m in ass.GetModules())
    {
    Console.WriteLine(
    "模块:"+m.Name);
    }

    MethodInfo[] methods
    = type.GetMethods();
    foreach (MethodInfo m in methods)
    {
    Console.WriteLine(
    "方法"+m.Name); //显示所有的共有方法
    }

    FieldInfo[] fields
    = type.GetFields();
    foreach (FieldInfo f in fields)
    {
    Console.WriteLine(
    "字段信息:"+f.Name);
    }

    PropertyInfo[] propertys
    = type.GetProperties();
    foreach( PropertyInfo p in propertys)
    {
    Console.WriteLine(
    "属性:"+p.Name);
    }

    ConstructorInfo[] ci1
    = type.GetConstructors();
    foreach (ConstructorInfo ci in ci1)
    {
    Console.WriteLine(
    "构造函数:"+ci.ToString()); //获得构造函数的形式

    }

    //*******************接口***************************************

    Console.WriteLine(
    "*******接口*****************************************");

    MyDll.ITest obj1
    = (MyDll.ITest)ass.CreateInstance(className);//这里必须是实现接口的类名,因为接口不能实例化
    //MyDll.ReflectTest obj2= (MyDll.ReflectTest)ass.CreateInstance(className);
    //典型的工厂模式
    int i = obj1.add();
    Console.WriteLine(i);


    //*****************委托*******************************************

    TestDelegate myDelegate
    = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "PrintString");
    //动态创建委托的简单例子
    Console.WriteLine(myDelegate(" 动态调用委托"));


    //*****************获得解决方案的所有Assembly********************

    Assembly[] assemblys
    = AppDomain.CurrentDomain.GetAssemblies();
    //遍历显示每个Assembly的名字
    foreach (object var in assemblys)
    {
    Console.WriteLine(
    "所有的Assembly的名字:"+var.ToString());
    }


    Console.Read();



    }


    }
    }

     2.Attribute(特性)

    MADN的定义为:公共语言运行时允许添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据(metadata)保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。

    Attribute就是一种“附着物”——就像牡蛎吸附在船底或礁石上一样。这些附着物的作用是为它们的附着体追加上一些额外的信息(这些信息就保存在附着物的体内)——比如“这个类是我写的”或者“这个函数以前出过问题”等等。

    你可能会问:这跟注释有什么区别呢?

    当然有区别啦!注释是对程序源代码的一种说明,主要目的是给人看的,在程序被编译的时候会被编译器所丢弃,因此,它丝毫不会影响到程序的执行。而Attribute是程序代码的一部分,不但不会被编译器丢弃,而且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里,在程序运行的时候,你随时可以从元数据里提取出这些附加信息来决策程序的运行。

    例子:

    自定义Attribute类:VersionAttribute

    代码
    [AttributeUsage(AttributeTargets.Class)]
    public class VersionAttribute : Attribute
    {
    public string Name { get; set; }
    public string Date { get; set; }
    public string Describtion { get; set; }
    }

    使用自定义Attribute的Class:

    [Version(Name = "hyddd", Date = "2009-07-20", Describtion = "hyddd's class")]
    public class MyCode
    {
    //...
    }

    上面这个Class中的Attribute一般会被如何使用呢?

    代码
    class Program
    {
    static void Main(string[] args)
    {
    var info
    = typeof(MyCode);
    var classAttribute
    = (VersionAttribute)Attribute.GetCustomAttribute(info, typeof(VersionAttribute));
    Console.WriteLine(classAttribute.Name);
    Console.WriteLine(classAttribute.Date);
    Console.WriteLine(classAttribute.Describtion);
    }
    }
  • 相关阅读:
    git push 报错:missing Change-Id in commit message footer
    script命令录屏
    dubbo.xsd
    常规项目用到的jar包之maven的pom.xml
    WebSocket Demo
    对程序员有帮助的站点集锦
    java之finally的用法
    Java 中的四种引用
    字符串类型的对象与引用及字符串常量池详解
    如何掌握一项新的技能?
  • 原文地址:https://www.cnblogs.com/engine1984/p/1793307.html
Copyright © 2011-2022 走看看