19 C# 第十七章(一) 反射

反射的概念,用处

概念:反射是指对一个程序集中的元数据进行检查的过程。


用处
1)  访问程序集中类型的元数据。包括像完整的类型名,成员名的构造,及对一个构造进行修饰的特性。

2)  使用元数据,在运行时动态调用一个类型成员,而不是编译时绑定。

3)  枚举程序集中的所有类型,并搜索满足特定条件的类型。


使用 System.Type 访问元数据


基本功能
  • Type.Name :  类型名是什么
  • Type.IsPublic : 类型是public 的吗
  • Type.BaseType : 类型的基本类型是什么
  • Type.GetInterfaces() : 类型支持任何接口吗
  • Type.Assembly :  类型是在哪个程序集中定义的。
  • Type.GetProperties() :  类型的属性
  • Type.GetMethods() :  类型的方法
  • Type.GetFields() :  类型的字段

程序实例: (getType() 和 typeof() 的例子)

http://msdn.microsoft.com/zh-cn/library/58918ffs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Reflect_Sample
{
    class Program
    {
        public int m_Member1;
        public string m_Member2;


        static void Main(string[] args)
        {
            DateTime datatime = new DateTime();

            Console.WriteLine("==================================================");
            Console.WriteLine("Test GetType()");
            Console.WriteLine("==================================================");
            Type type = datatime.GetType();

            Console.WriteLine("Type is :{0} \n", type.FullName);
            foreach (System.Reflection.PropertyInfo property in type.GetProperties())
            {
                Console.WriteLine(property.Name);
            }

            Console.WriteLine("==================================================");
            Console.WriteLine("Test typeof()");
            Console.WriteLine("==================================================");

            Type t = typeof(Program);

            Console.WriteLine("Methods:");
            System.Reflection.MethodInfo[] methodInfo = t.GetMethods();

            foreach (System.Reflection.MethodInfo mInfo in methodInfo)
                Console.WriteLine("  " + mInfo.ToString());

            Console.WriteLine("Members:");
            System.Reflection.MemberInfo[] memberInfo = t.GetMembers();

            foreach (System.Reflection.MemberInfo mInfo in memberInfo)
                Console.WriteLine("  " + mInfo.ToString());

            Console.ReadKey();
        }
    }
}



成员调用


获取元数据并不是最终的目的,还可以更进一步动态调用它引用的成员。这里的例子主要是设置类中的属性值。其中包括静态的属性,普通的属性,和集合类型的

http://msdn.microsoft.com/zh-cn/library/vstudio/xb5dd1f1.aspx


程序实例: 使用反射来为对象的属性设置值
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

class Example
{
    private static int _staticProperty = 41;
    public static int StaticProperty
    {
        get
        {
            return _staticProperty;
        }
        set
        {
            _staticProperty = value;
        }
    }

    private int _instanceProperty = 42;
    public int InstanceProperty
    {
        get
        {
            return _instanceProperty;
        }
        set
        {
            _instanceProperty = value;
        }
    }

    private Dictionary<int, string> _indexedInstanceProperty = new Dictionary<int, string>();
    // By default, the indexer is named Item, and that name must be used
    // to search for the property. In this example, the indexer is given
    // a different name by using the IndexerNameAttribute attribute.
    [IndexerNameAttribute("IndexedInstanceProperty")]
    public string this[int key]
    {
        get
        {
            string returnValue = null;
            if (_indexedInstanceProperty.TryGetValue(key, out returnValue))
            {
                return returnValue;
            }
            else
            {
                return null;
            }
        }
        set
        {
            if (value == null)
            {
                throw new ApplicationException("IndexedInstanceProperty value can be the empty string, but it cannot be Nothing.");
            }
            else
            {
                if (_indexedInstanceProperty.ContainsKey(key))
                {
                    _indexedInstanceProperty[key] = value;
                }
                else
                {
                    _indexedInstanceProperty.Add(key, value);
                }
            }
        }
    }

    public static void Main()
    {
        Console.WriteLine("Initial value of class-level property: {0}", Example.StaticProperty);

        PropertyInfo piShared = typeof(Example).GetProperty("StaticProperty");
        piShared.SetValue(null, 76, null);

        Console.WriteLine("Final value of class-level property: {0}",Example.StaticProperty);


        Example exam = new Example();

        Console.WriteLine("\nInitial value of instance property: {0}", exam.InstanceProperty);

        PropertyInfo piInstance = typeof(Example).GetProperty("InstanceProperty");
        piInstance.SetValue(exam, 37, null);

        Console.WriteLine("Final value of instance property: {0}", exam.InstanceProperty);


        exam[17] = "String number 17";
        exam[46] = "String number 46";
        exam[9] = "String number 9";

        Console.WriteLine("\nInitial value of indexed instance property(17): '{0}'", exam[17]);

        // By default, the indexer is named Item, and that name must be used
        // to search for the property. In this example, the indexer is given
        // a different name by using the IndexerNameAttribute attribute.
        PropertyInfo piIndexedInstance = typeof(Example).GetProperty("IndexedInstanceProperty");
        piIndexedInstance.SetValue(exam,
                                   "New value for string number 17",
                                   new object[] { (int)17 });

        Console.WriteLine("Final value of indexed instance property(17): '{0}'", exam[17]);

        Console.ReadKey();
    }
}



泛型类型的反射

在泛型类型上执行运行时反射,将判断出一个类或方法是否包含泛型类型,并确定它包含的任何类型的参数。

1)  判断类型参数的类型

public class Stack<T>
{
    public void Add(T i)
    {
        Type t = typeof(T);  // 这里可以判断泛型参数的类型。
    }
}



2)  判断类或方法是否支持泛型, 获取泛型类或方法类型参数

程序实例: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Reflect_GenericType_Sample
{
    class Program
    {
        static void Main(string[] args)
        {
            Type type;
            type = typeof(Stack<>);

            Console.WriteLine("Stack<>  ContainsGenericParameters = {0}", type.ContainsGenericParameters);
            Console.WriteLine("Stack<>  IsGenericType = {0}", type.IsGenericType);

            Console.WriteLine("");
            type = typeof(Stack<int>);


            Console.WriteLine("Stack<int>  ContainsGenericParameters = {0}", type.ContainsGenericParameters);
            Console.WriteLine("Stack<int>  IsGenericType = {0}", type.IsGenericType);

            Console.WriteLine("==============================================================");
            Console.WriteLine("Test get generic type arguments");
            Console.WriteLine("==============================================================");
            Stack<string> s = new Stack<string>();
            Type subt = s.GetType();

            foreach(Type t in subt.GetGenericArguments())
            {
                Console.WriteLine("params: {0}", t.FullName);
            }

            Console.ReadKey();
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值