zoukankan      html  css  js  c++  java
  • 第十章 管理类型(In .net4.5) 之 使用反射

    1. 概述

      一个.net程序不仅包含代码和数据,还包含 元数据

      本章介绍如何应用attributes以及如何使用反射来获取它,还有如何使用CodeDomexpression trees来实现在运行时生成代码。

    2. 主要内容

      2.1 创建和使用attributes

        ① attributes用来向程序添加元数据。可以应用到所有类型:程序集、类、方法、参数、属性。

    [Conditional("CONDITION1"), Conditional("CONDITION2")]
    static void MyMethod() { }

        ② AssemblyInfo.cs中保存的是应用到当前程序集的所有attributes。

        ③ 可以使用attributes的IsDefined和GetCustomAttribute方法读取attributes

    if (Attribute.IsDefined(typeof(Person), typeof(SerializableAttribute)))
    {  }
    
    ConditionalAttribute conditionalAttribute = 
        (ConditionalAttribute)Attribute.GetCustomAttribute(
        typeof(ConditionalClass),
        typeof(ConditionalAttribute));
    
    string condition = conditionalAttribute.ConditionString; //CONDITION1

        ④ 可以自定义attributes

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, 
        AllowMultiple=true)]
    class CompleteCustomAttribute : Attribute
    {
        public CompleteCustomAttribute(string description)
        {
            Description = description;
        }
        public string Description {get; set; }
    }

      2.2 使用反射

        反射 使得一个应用程序可以收集自身的信息并使用。反射的运行速度比其他静态代码慢。

    public interface IPlugin
    {
        string Name { get; }
        string Description {get; }
        bool Load(MyApplication application);
    }
    
    Assembly pluginAssembly = Assembly.Load("assemblyName");
    
    var plugins = from type in pluginAssembly.GetTypes()
        where typeof(IPlugin).IsAssignableFrom(type) && !type.IsInterface
        select type;
    
    foreach(Type pluginType in plugins)
        IPlugin plugin = Activitor.CreateInstance(pluginType) as IPlugin;

        使用反射还可以获取属性的值和执行指定的方法。

    int i = 42;
    MethodInfo compareToMethod = i.GetType().GetMethod("CompareTo"
        , new Type[] { typeof(int) };
    int result = (int)compareToMethod.Invoke(i, new object[] { 41 });

      2.3 使用CodeDom和Lambda表达式生成代码

        ① 使用CodeDom

    CodeCompileUnit compileUnit = new CodeCompileUnit();
    CodeNamespace myNamespace = new CodeNamespace("MyNamespace");
    myNamespace.Imports.Add(new CodeNamespaceImport("System"));
    CodeTypeDeclaration myClass = new CodeTypeDeclaration("MyClass");
    CodeEntryPointMethod start = new CodeEntryPointMethod();
    CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodePrimitiveExpression("Hello World!"));
    
    compileUnit.Namespaces.Add(myNamespace);
    myNamespace.Types.Add(myClass);
    myClass.Members.Add(start);
    start.Statements.Add(cs1);

        编译单元定义完成后,使用CSharpCodeProvider来执行生成。

    CSharpCodeProvider provider = new CSharpCodeProvider();
    
    using(StreamWriter sw = new StreamWriter("HelloWorld.cs", false))
    {
        IndentedTextWriter tw = new IndentedTypeWriter(sw, "    ");
        provider.GenerateCodeFromCompileUnit(compileUnit, tw, new CodeGeneratorOptions());
        tw.Close();
    }

        ② 使用 expression trees 实现上述功能

    BlockExpression blockExpr = Expression.Block(
        Expression.Call(
            null,
            typeof(Console).GetMethod("Write", new Type[] { typeof(String)}), Expression.Constant("Hello ")
        ),
        Expression.Call(
            null,
            typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String)}), Expression.Constant("World!")
        ),
    );    
    
    Expression.Lambda<Action>(blockExpr).Compile();

    3. 总结

      ① 一个C#程序集包括代码和元数据。

      ② Attributes是元数据的一种,可以被应用到代码中,可以在运行时被查询到。

      ③ 反射是一个在C#程序中检查元数据的过程。

      ④ 利用反射,可以 创建类型、调用方法、读取属性 等等。

      ⑤ CodeDom用于在运行时创建一个编译单元。可以被编译或转化成源码文件。

      ⑥ 表达式树 描述一块代码,可以被翻译成其他语言(比如sql),也可以被编译和执行。

  • 相关阅读:
    【转】Oracle 查询每天执行慢的SQL
    【转】StringBuilder与String的区别
    【转】C#单例模式实现
    【转】设计模式
    【转】十大排序算法
    ASP.NET jQuery 随笔 从DropDownList获取选择的text和value值
    ASP.NET jQuery 随笔 显示CheckBoxList成员选中的内容
    ASP.NET jQuery 随笔 在TextBox里面阻止复制、剪切和粘贴事件
    ASP.NET JQuery 随笔-搜索框默认提示
    JS 某一区域内所有CheckBox全选和取消全选(.net)
  • 原文地址:https://www.cnblogs.com/stone_lv/p/4368684.html
Copyright © 2011-2022 走看看