1. 程式人生 > >C# 中那些常用的工具類(Utility Class)(三)

C# 中那些常用的工具類(Utility Class)(三)

asp call ast eba order com 引用 creat 信息

  今天就平常用到的非常多的反射這個技術來做一個總結,當然關於反射需要講解的東西實在是太多的內容,在一片文章中想要講解清楚是非常難的,本篇博客也是就自己本人對這些內容學習後的一個總結,當然包括看書和自己寫過的一些代碼中抽取的一些示例,而且本文也僅限於此時對於這個知識點的理解,希望通過以後的逐步學習能夠不斷加深對這個知識點的理解。

  首先來看看對於反射的基礎知識點。

1 定義:首先看看MSDN怎樣對它進行解釋吧

  反射提供了封裝程序集、模塊和類型的對象(Type 類型)。可以使用反射動態創建類型的實例,將類型綁定到現有對象,或從現有對象獲取類型並調用其方法或訪問其字段和屬性。如果代碼中使用了屬性,可以利用反射對它們進行訪問。

  2 反射有什麽作用?

 A、將類型綁定到現有對象,或從現有對象中獲取類型信息,這些信息包括(Assembly MemberInfo EventInfo FieldInfo MethodBase ConstructorInfo MethodInfo PropertyInfo 等等 )另外可以使用反射動態地創建類型的實例,

     例如:
      1、System.Activator 的CreateInstance方法。該方法返回新對象的引用。
      2、System.Activator 的CreateInstanceFrom 與上一個方法類似,不過需要指定類型及其程序集
      3、System.Appdomain 的方法:CreateInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap
      4、System.Type的InvokeMember 實例方法:這個方法返回一個與傳入參數相符的構造函數,並構造該類型。
      5、System.Reflection.Constructinfo 的Invoke實例方法

     下面通過一段代碼來了解這5種創建實例的方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using OptimizeReflection;
using System.Collections;
using System.Web;

namespace TestOptimizeReflection
{
	public class OrderInfo
	{
		public int OrderID { get; set; }
		public DateTime OrderDate { get; set; }
		public decimal SumMoney { get; set; }
		public string Comment { get; set; }
		public bool Finished { get; set; }

		public int Add(int a, int b)
		{
			return a + b;
		}		
	}

	class Program
	{
		static void Main()
		{
            TestNewInstance();
		}

        static void TestNewInstance()
        {
            //常規方法創建對象
            OrderInfo testObj = new OrderInfo();

            #region 常規反射創建
            //利用反射來動態創建對象
            Type instanceType = typeof(OrderInfo);
            OrderInfo orderInfo = (OrderInfo)Activator.CreateInstance(instanceType);
            #endregion

            #region Activator.CreateInstanceFrom 創建
            //註意Assembly.GetEntryAssembly().CodeBase表示當前執行的exe所在的路徑,instanceType.FullName表示當前OrderInfo的類型名稱TestOptimizeReflection.OrderInfo
            System.Runtime.Remoting.ObjectHandle oh= Activator.CreateInstanceFrom(Assembly.GetEntryAssembly().CodeBase, instanceType.FullName);
            //返回被包裝的對象
            OrderInfo orderInfoEx = (OrderInfo)oh.Unwrap();
            #endregion

            #region System.AppDomain.CurrentDomain實例創建對象
            System.Runtime.Remoting.ObjectHandle ohEx = System.AppDomain.CurrentDomain.CreateInstance(Assembly.GetEntryAssembly().FullName, instanceType.FullName);
            OrderInfo orderInfoExEx = (OrderInfo)ohEx.Unwrap();
            //合並上面的兩步
            OrderInfo orderInfoExExEx = (OrderInfo)System.AppDomain.CurrentDomain.CreateInstanceAndUnwrap(Assembly.GetEntryAssembly().FullName, instanceType.FullName);
            #endregion

            #region InvokeMember方法創建實例
            OrderInfo invokeMemberOrderInfo = (OrderInfo)instanceType.InvokeMember(null, BindingFlags.Public| BindingFlags.Instance | BindingFlags.Static|BindingFlags.CreateInstance, System.Type.DefaultBinder, null, null);
            #endregion

            #region 調用構造器創建
            //調用無參數的默認構造函數
            ConstructorInfo ci = instanceType.GetConstructor(new Type[] { });
            OrderInfo ciOrderInfo = (OrderInfo)ci.Invoke(null);
            #endregion
        }
	}
}  

    B、應用程序需要在運行時從某個特定的程序集中載入一個特定的類型,以便實現某個任務時可以用到反射。

      這個該怎樣去理解呢?這個可以用插件系統中的同類思想去解釋,在構建插件系統的時候,我們有時候需要主程序去動態地調用插件,可能應用程序只有在執行某一操作的時候才能夠去調用相關的DLL,這個時候我們就可以通過反射這種方式來動態調用dll中分特定方法或者類型,這個也是經常使用到的。
    C、反射主要應用與類庫,這些類庫需要知道一個類型的定義,以便提供更多的功能。

    D、反射能夠調用一些私有方法和字段等。

     這個需要重點去講述,我們知道常規的實例方法由於受到作用域的影響,很多時候當方法設置為Private或者是其它的限制訪問的關鍵字時就無能為力了,這個也是完全能夠體現類的封裝性,但是通過反射就能夠完全繞開這些限制,下面舉出一些對私有變量或字段、方法的一些訪問方式,能夠直接進行訪問,這樣還是非常方便的,具體請參考下面的代碼。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Dvap.Infrastructure.Utils
{
    public static class ReflectionUtil
    {
        /// <summary>
        /// 得到私有字段的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instance"></param>
        /// <param name="fieldname"></param>
        /// <returns></returns>
        public static T GetPrivateField<T>(this object instance, string fieldname)
        {
            BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
            Type type = instance.GetType();
            FieldInfo field = type.GetField(fieldname, flag);
            return (T)field.GetValue(instance);
        }

        /// <summary>
        /// 設置私有成員的值
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="fieldname"></param>
        /// <param name="value"></param>
        public static void SetPrivateField(this object instance, string fieldname, object value)
        {
            BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
            Type type = instance.GetType();
            FieldInfo field = type.GetField(fieldname, flag);
            field.SetValue(instance, value);
        }

        /// <summary>
        /// 得到私有屬性的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instance"></param>
        /// <param name="propertyname"></param>
        /// <returns></returns>
        public static T GetPrivateProperty<T>(this object instance, string propertyname)
        {
            BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
            Type type = instance.GetType();
            PropertyInfo field = type.GetProperty(propertyname, flag);
            return (T)field.GetValue(instance, null);
        }      

        /// <summary>
        /// 設置私有屬性的值
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="propertyname"></param>
        /// <param name="value"></param>
        public static void SetPrivateProperty(this object instance, string propertyname, object value)
        {
            BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
            Type type = instance.GetType();
            PropertyInfo field = type.GetProperty(propertyname, flag);
            field.SetValue(instance, value, null);
        }

        /// <summary>
        /// 調用私有方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instance"></param>
        /// <param name="name"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public static T CallPrivateMethod<T>(this object instance, string name, params object[] param)
        {
            BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic;
            Type type = instance.GetType();
            MethodInfo method = type.GetMethod(name, flag);
            return (T)method.Invoke(instance, param);
        }
    }
}

  

C# 中那些常用的工具類(Utility Class)(三)