类型反射、晚期绑定和基于特性的编程_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 类型反射、晚期绑定和基于特性的编程

类型反射、晚期绑定和基于特性的编程

 2017/10/11 23:25:43  绛河  程序员俱乐部  我要评论(0)
  • 摘要:1、反射为何要关注元数据?------反射服务在.net中,通过反射可以得到一个给定的.dll或.exe程序集所包含的所有类型的列表,列表包括给定类型定义的方法、字段、属性和事件,反射即反向获得。如何使用System.Reflection命名空间编程读取.net元数据?需要借助System.Type类。usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem
  • 标签:反射 编程

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("\n***** 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("\nEnter 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 *****\n");
            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}\n", 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 *****\n");
            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}\n",
                          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

发表评论
用户名: 匿名