浅析.NET的反射特性

     在.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   

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏有趣的Python

慕课网-C++远征之多态篇(下)-学习笔记

RTTI(运行时类型识别) Run-Time Type Identification typeid < - > dynamic_cast 例子: class F...

3364
来自专栏程序员维他命

《Effective Objective-C 》干货三部曲(三):技巧篇

继上一篇《Effective Objective-C 》超级干货三部曲(二):规范篇之后,本篇即是三部曲的第三篇:技巧篇。本篇作为三部曲的最终篇,归纳讲解的是本...

1142
来自专栏我是攻城师

关于线程死锁,活锁和饥饿问题

上篇文章介绍了Java多线程里面最常见的死锁问题,其实除了死锁问题,这有两种问题虽然不常见,但是也需要我们了解一下,分别是线程活锁和线程饥饿。

962
来自专栏MelonTeam专栏

浅析Android中的ThreadLocal

ThreadLocal第一眼很容易让人误以为这是一个Thread,其实并不是,它是在JDK 1.2中引入,为每个线程提供一个独立的本地变量副本,用来解决变量并发...

17310
来自专栏Hongten

spring开发_BeanPostProcessor_Bean后处理器

http://www.cnblogs.com/hongten/gallery/image/112581.html

572
来自专栏Android机动车

RxJava从入门到不离不弃(四)——过滤操作符

RxJava中的过滤操作符,顾名思义,这类操作符主要用于对事件数据的筛选过滤,只返回满足我们条件的数据。

723
来自专栏王金龙的专栏

Java设计模式——线程安全的单件模式

  单件模式的类图是所有模式的类图中最简单的——只有一个类。尽管从类设计的视角来看单件模式很简单,但是实现上还是会遇到一些问题,本文着重对这一点来进行分析解决。

571
来自专栏大内老A

WCF技术剖析之十三:序列化过程中的已知类型(Known Type)

DataContractSerializer承载着所有数据契约对象的序列化和反序列化操作。在上面一篇文章(《数据契约(Data Contract)和数据契约序列...

19310
来自专栏菩提树下的杨过

深度解析 TypeConverter & TypeConverterAttribute (一)

前言     我们在开发复杂控件的时候不可避免的碰到类型转换TypeConverter,微软给我们提供了很多转换类如ArrayConverter,BaseNu...

1986
来自专栏Phoenix的Android之旅

如何方便的收集app崩溃日志

很多人可能没了解过这个东西可以干嘛用, 其实它的作用是可以传入一个 Handler来捕获那些没有被捕获的异常, 比如 app 层面的 crash。 下面提供了一...

842

扫码关注云+社区