淺析.NET的反射特性

weixin_34162629發表於2016-10-22

     在.net框架體系內,反射特性較多的應用到。反射的相關定義分為兩種。

     自然解釋:射是一種自然現象,表現為受刺激物對刺激物的逆反應;這是反射的字面解釋,我們看一下計算機程式設計中的反射;

     程式設計解釋:通過 System.Reflection 名稱空間中的類以 System.Type您可以獲取有關已載入的程式集和在其中定義的型別(如介面值型別)的資訊。 您也可以使用反射在執行時建立型別例項,以及呼叫和訪問這些實。

     反射(Reflection)有下列用途:它允許在執行時檢視屬性(attribute)資訊;它允許審查集合中的各種型別,以及例項化這些型別;它允許延遲繫結的方法和屬性(property);它允許在執行時建立新型別,然後使用這些型別執行一些任務。

     下面介紹一下有關反射的程式集的相關屬性和方法的原始碼:

        (1).Object的GetType()方法:

    // Returns a Type object which represent this object instance.
    // 
    [System.Security.SecuritySafeCritical]  // auto-generated
    [Pure]
    [ResourceExposure(ResourceScope.None)]
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    public extern Type GetType();

      (2).PropertyInfo的GetProperty()方法:

 public PropertyInfo GetProperty(String name,BindingFlags bindingAttr,Binder binder, 
                        Type returnType, Type[] types, ParameterModifier[] modifiers)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,bindingAttr,binder,returnType,types,modifiers);
        }

        public PropertyInfo GetProperty(String name, Type returnType, Type[] types,ParameterModifier[] modifiers)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,types,modifiers);
        }

        public PropertyInfo GetProperty(String name, BindingFlags bindingAttr)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,bindingAttr,null,null,null,null);
        }

        public PropertyInfo GetProperty(String name, Type returnType, Type[] types)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,types,null);
        }

        public PropertyInfo GetProperty(String name, Type[] types)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (types == null)
                throw new ArgumentNullException("types");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,null,types,null);
        }

        public PropertyInfo GetProperty(String name, Type returnType)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (returnType == null)
                throw new ArgumentNullException("returnType");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,null,null);
        }

        internal PropertyInfo GetProperty(String name, BindingFlags bindingAttr, Type returnType)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            if (returnType == null)
                throw new ArgumentNullException("returnType");
            Contract.EndContractBlock();
            return GetPropertyImpl(name, bindingAttr, null, returnType, null, null);
        }

        public PropertyInfo GetProperty(String name)
        {
            if (name == null)
                throw new ArgumentNullException("name");
            Contract.EndContractBlock();
            return GetPropertyImpl(name,Type.DefaultLookup,null,null,null,null);
        }

   (3).Object的GetValue()方法:

[DebuggerStepThroughAttribute]
        [Diagnostics.DebuggerHidden]
        public Object GetValue(Object obj)
        {
            return GetValue(obj, null);
        }

        [DebuggerStepThroughAttribute]
        [Diagnostics.DebuggerHidden]
        public virtual Object GetValue(Object obj,Object[] index)
        {
            return GetValue(obj, BindingFlags.Default, null, index, null);
        }

        public abstract Object GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture);

  以上介紹了一下有關反射的相關方法的底層方法原始碼,現在介紹一下較為通用的方法:

    (1).獲取物件的所有公共屬性。

        /// <summary>
        /// 獲取物件的所有公共屬性。
        /// </summary>
        /// <param name="obj">定義該方法的資料型別。</param>
        /// <returns>返回包含該物件的屬性資訊的陣列。</returns>
        public static IEnumerable<PropertyInfo> GetProperties(this object obj)
        {
            return obj.GetType().GetProperties();
        }

    (2).獲取一個物件的屬性。

        /// <summary>
        ///獲取一個物件的屬性。
        /// </summary>
        /// <param name="obj">定義該方法的資料型別。gb</param>
        /// <param name="flags">提供要確定要檢索的屬性的標誌。</param>
        /// <returns>返回包含該物件的屬性資訊的陣列。</returns>
        public static IEnumerable<PropertyInfo> GetProperties(this object obj, BindingFlags flags)
        {
            return obj.GetType().GetProperties(flags);
        }

    (3).用指定名稱獲取具有指定名稱的屬性的當前物件的屬性值。

        /// <summary>
        ///用指定名稱獲取具有指定名稱的屬性的當前物件的屬性值。
        /// </summary>
        /// <param name="obj">要檢索的屬性值的物件。</param>
        /// <param name="propertyName">要檢索的屬性的名稱。</param>
        /// <returns>返回屬性的值。</returns>
        public static object GetPropertyValue(this object obj, string propertyName)
        {
            var item = obj.GetType().GetProperty(propertyName);

            if (item == null) return null;
            var value = obj.GetType().GetProperty(propertyName).GetValue(obj);

            if (item.PropertyType.IsGenericType)
            {
                value = item.PropertyType.GetProperty(propertyName);
            }
            return value;
        }

     (4).獲取一個列舉字串值。

        /// <summary>
        ///獲取一個列舉字串值。
        /// </summary>
        /// <param name="obj">該列舉返回的字串值。</param>
        /// <returns>返回一個列舉字串值。</returns>
        public static string GetStringValue(this System.Enum obj)
        {
            var fieldInfo = obj.GetType().GetField(obj.ToString());
            var attributes = fieldInfo.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];

            var output = (StringValueAttribute)attributes.GetValue(0);

            return output.Text;
        }

     (5).獲取方法呼叫。

        /// <summary>
        /// 獲取方法呼叫
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <returns></returns>
        public static MethodCallExpression GetMethodCall<T>(Expression<T>  action )
        {
            var call = action.Body as MethodCallExpression;

            return call;
        }

    (6).獲取型別名稱.

        /// <summary>
        /// 獲取型別名稱
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static string GetTypeName<T>()
        {
            return typeof (T).Name;
        }

    (7).獲取引數值

        /// <summary>
        /// 獲取引數值
        /// </summary>
        /// <param name="methodCall"></param>
        /// <returns></returns>
        public static IEnumerable<Tuple<ParameterInfo, object>> GetArgumentValues(MethodCallExpression methodCall)
        {
            var parameters = methodCall.Method.GetParameters();
            if (!parameters.Any()) yield break;
            for(var i = 0; i < parameters.Length; i++)
            {
                var arg = methodCall.Arguments[i];

                var ceValue = arg as ConstantExpression;

                if (ceValue != null)
                    yield return new Tuple<ParameterInfo, object>(parameters[i], ceValue.Value);
                else
                    yield return new Tuple<ParameterInfo, object>(parameters[i], GetExpressionValue(arg));
            }
        }

    (8).獲取表示式值

        /// <summary>
        /// 獲取表示式值
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private static object GetExpressionValue(Expression expression)
        {
            var lambda = Expression.Lambda<Func<object>>(Expression.Convert(expression, typeof (object)));
            var func = lambda.Compile();
            return func();
        }

    反射類的繼承層次如下:

      System.reflection  

      System.Reflection.Assembly 

  System.Reflection.MemberInfo
  System.Reflection.EventInfo
  System.Reflection.FieldInfo
  System.Reflection.MethodBase
  System.Reflection.ConstructorInfo
  System.Reflection.MethodInfo
  System.Reflection.PropertyInfo
  System.Type   

 

相關文章