zoukankan      html  css  js  c++  java
  • 类型反射、晚期绑定和基于特性的编程

    1、反射

    为何要关注元数据?------反射服务

    在.net中,通过反射可以得到一个给定的.dll或.exe程序集所包含的所有类型的列表,列表包括给定类型定义的方法、字段、属性和事件,反射即反向获得。

    如何使用System.Reflection命名空间编程读取.net元数据?需要借助System.Type类。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.Reflection;
    using System.IO;  // For FileNotFoundException definition.
    
    namespace ExternalAssemblyReflector
    {
        class Program
        {
            #region Helper function
            static void DisplayTypesInAsm(Assembly asm)
            {
                Console.WriteLine("
    ***** Types in Assembly *****");
                Console.WriteLine("->{0}", asm.FullName);
                Type[] types = asm.GetTypes();
                foreach (Type t in types)
                    Console.WriteLine("Type: {0}", t);
                Console.WriteLine("");
            }
            #endregion
    
            static void Main(string[] args)
            {
                Console.WriteLine("***** External Assembly Viewer *****");
    
                string asmName = "";
                Assembly asm = null;
    
                do
                {
                    Console.WriteLine("
    Enter an assembly to evaluate");
                    Console.Write("or enter Q to quit: ");
    
                    // Get name of assembly.
                    asmName = Console.ReadLine();
    
                    // Does user want to quit?
                    if (asmName.ToUpper() == "Q")
                    {
                        
                        break;
                    }
    
                    // Try to load assembly.
                    try
                    {
                        asm = Assembly.LoadFrom(asmName);
                        DisplayTypesInAsm(asm);
                    }
                    catch
                    {
                        Console.WriteLine("Sorry, can't find assembly.");
                    }
                } while (true);
            }
        }
    }

    2、晚期绑定

    创建一个给定类型的实例,并且在运行时调用其成员,而不需要在编译时知道它存在的一种技术,对于程序的可扩展性来说很重要。

    晚期绑定的关键是System.Activator类。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Reflection;
    
    namespace LateBindingApp
    {
        // This program will load an external library, 
        // and create an object using late binding.
        public class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("***** Fun with Late Binding *****");
                // Try to load a local copy of CarLibrary.
                Assembly a = null;
                try
                {
                    a = Assembly.Load("CarLibrary");
                }
                catch (FileNotFoundException ex)
                {
                    Console.WriteLine(ex.Message);
                    return;
                }
    
                if (a != null)
                {
                    // CreateUsingLateBinding(a);
                    InvokeMethodWithArgsUsingLateBinding(a);
                }
    
                Console.ReadLine();
            }
    
            #region Invoke method with no args
            static void CreateUsingLateBinding(Assembly asm)
            {
                try
                {
                    // Get metadata for the Minivan type.
                    Type miniVan = asm.GetType("CarLibrary.MiniVan");
    
                    // Create the Minivan on the fly.
                    object obj = Activator.CreateInstance(miniVan);
                    Console.WriteLine("Created a {0} using late binding!", obj);
    
                    // Get info for TurboBoost.
                    MethodInfo mi = miniVan.GetMethod("TurboBoost");
    
                    // Invoke method ('null' for no parameters).
                    mi.Invoke(obj, null);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            #endregion
    
            #region Invoke method with args
            static void InvokeMethodWithArgsUsingLateBinding(Assembly asm)
            {
                try
                {
                    // First, get a metadata description of the sports car. 
                    Type sport = asm.GetType("CarLibrary.SportsCar");
    
                    // Now, create the sports car.
                    object obj = Activator.CreateInstance(sport);
    
                    // Invoke TurnOnRadio() with arguments.
                    MethodInfo mi = sport.GetMethod("TurnOnRadio");
                    mi.Invoke(obj, new object[] { true, 2 });
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            #endregion
        }
    }

    3、.net特性的作用。 

    .net平台允许程序员使用特性把更多的元数据嵌入到程序集中,特性就是用于类型(比如类、接口和结构)、成员(比如属性、方法)、程序集或模块的代码注解。

    一个特性直到另一个软件反射它的值时才有用。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ApplyingAttributes
    {
        #region Simple classes for testing
        // This class can be saved to disk.
        [Serializable]
        public class Motorcycle
        {
            // However this field will not be persisted.
            [NonSerialized]
            float weightOfCurrentPassengers;
    
            // These fields are still serializable.
            bool hasRadioSystem;
            bool hasHeadSet;
            bool hasSissyBar;
        }
    
        [Serializable, Obsolete("Use another vehicle!")]
        public class HorseAndBuggy
        {
            // ...
        }
        #endregion
    
        class Program
        {
            static void Main(string[] args)
            {
                HorseAndBuggy mule = new HorseAndBuggy();
            }
        }
    }

    反射特性

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using AttributedCarLibrary;
    
    namespace VehicleDescriptionAttributeReader
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("***** Value of VehicleDescriptionAttribute *****
    ");
                ReflectOnAttributesWithEarlyBinding();
                Console.ReadLine();
            }
    
            private static void ReflectOnAttributesWithEarlyBinding()
            {
                // Get a Type representing the Winnebago.
                Type t = typeof(Winnebago);
    
                // Get all attributes on the Winnebago.
                object[] customAtts = t.GetCustomAttributes(false);
    
                // Print the description.
                foreach (VehicleDescriptionAttribute v in customAtts)
                    Console.WriteLine("-> {0}
    ", v.Description);
            }
        }
    }

    特性晚绑定

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using System.Reflection;
    
    namespace VehicleDescriptionAttributeReaderLateBinding
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("***** Value of VehicleDescriptionAttribute *****
    ");
                ReflectAttributesUsingLateBinding();
                Console.ReadLine();
            }
    
            #region Helper method
            private static void ReflectAttributesUsingLateBinding()
            {
                try
                {
                    // Load the local copy of AttributedCarLibrary.
                    Assembly asm = Assembly.Load("AttributedCarLibrary");
    
                    // Get type info of VehicleDescriptionAttribute.
                    Type vehicleDesc =
                      asm.GetType("AttributedCarLibrary.VehicleDescriptionAttribute");
    
                    // Get type info of the Description property.
                    PropertyInfo propDesc = vehicleDesc.GetProperty("Description");
    
                    // Get all types in the assembly.
                    Type[] types = asm.GetTypes();
    
                    // Iterate over each type and obtain any VehicleDescriptionAttributes.
                    foreach (Type t in types)
                    {
                        object[] objs = t.GetCustomAttributes(vehicleDesc, false);
    
                        // Iterate over each VehicleDescriptionAttribute and print
                        // the description using late binding.
                        foreach (object o in objs)
                        {
                            Console.WriteLine("-> {0}: {1}
    ",
                              t.Name, propDesc.GetValue(o, null));
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            #endregion
        }
    }

    4、可扩展应用程序

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Reflection;
    
    using CommonSnappableTypes;
    
    namespace MyExtendableApp
    {
        public partial class MainForm : Form
        {
            public MainForm()
            {
                InitializeComponent();
            }
    
            #region Menu handler
            private void snapInModuleToolStripMenuItem_Click(object sender,
              EventArgs e)
            {
                // Allow user to select an assembly to load.
                OpenFileDialog dlg = new OpenFileDialog();
    
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    if (dlg.FileName.Contains("CommonSnappableTypes"))
                        MessageBox.Show("CommonSnappableTypes has no snap-ins!");
                    else if (!LoadExternalModule(dlg.FileName))
                        MessageBox.Show("Nothing implements IAppFunctionality!");
                }
            }
            #endregion
    
            #region Load external assembly
            private bool LoadExternalModule(string path)
            {
                bool foundSnapIn = false;
                Assembly theSnapInAsm = null;
    
                try
                {
                    // Dynamically load the selected assembly.
                    theSnapInAsm = Assembly.LoadFrom(path);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return foundSnapIn;
                }
    
                // Get all IAppFunctionality compatible classes in assembly.
                var theClassTypes = from t in theSnapInAsm.GetTypes()
                                    where t.IsClass &&
                                    (t.GetInterface("IAppFunctionality") != null) 
                                    select t;
    
                // Now, create the object and call DoIt() method.
                foreach (Type t in theClassTypes)
                {
                    foundSnapIn = true;
                    // Use late binding to create the type.
                    IAppFunctionality itfApp =
                      (IAppFunctionality)theSnapInAsm.CreateInstance(t.FullName, true);
                    itfApp.DoIt();
                    lstLoadedSnapIns.Items.Add(t.FullName);
    
                    // Show company info.
                    DisplayCompanyData(t);
    
                }
                return foundSnapIn;
            }
            #endregion
    
            #region Show company info
            private void DisplayCompanyData(Type t)
            {
                // Get [CompanyInfo] data.
                var compInfo = from ci in t.GetCustomAttributes(false)
                               where
                                   (ci.GetType() == typeof(CompanyInfoAttribute))
                               select ci;
    
                // Show data.
                foreach (CompanyInfoAttribute c in compInfo)
                {
                    MessageBox.Show(c.CompanyUrl,
                      string.Format("More info about {0} can be found at", c.CompanyName));
                }
            }
            #endregion
        }
    }

     更详细的基础例子参照:http://www.jb51.net/article/56029.htm

  • 相关阅读:
    -Prefix.pch has been modified 的错误修复
    Xcode插件,模板安装
    php 内置函数JSON处理
    OC 创建单例
    UITabBarController 的配置
    execute、executeQuery和executeUpdate之间的区别
    iOS类方法实例方法 与 self
    iOS U7ea2 乱码 转换
    PHP 页面跳转的三种方式
    C#数组 动态添加元素
  • 原文地址:https://www.cnblogs.com/janghe/p/7653049.html
Copyright © 2011-2022 走看看