反射与属性


反射是编程的读取与类型相关联的元数据的行为,通过元数据,你能了解它是什么类型以及它是由什么构成的(方法、属性、基类).
反射服务在system.Reflection命名空间中定义,它在和属性一起使用时最有用。
属性是一种向类型添加信息并影响类型行为的方法。
反射还允许在运行期间定义新类型,并生成相应的IL代码和元数据(使用在System.Reflection.Emit命名空间中的各种服务。
 
System.Type
基类Object定义了GetType()方法,使得你能对任何.NET对象调用这个方法
public class MyClass
{ ... }
 
int number = 0;
MyClass obj = new MyClass();
 
Type type1 = number.GetType();
Type type2 = number.GetType();
 
typeof运算符允许你直接检索与一个类型相关联的Type值,而无需实例化该类型的一个对象
Type type1 = typeof(int);
Type type2 = typeof(MyClass);
 
Type使你可以获取类型的元数据
 
Type type = typeof(MyClass);
string name = type.ToString();
Debug.Assert(name == “MyClass”);
 
示例:使用Type.GetMethods() 来反射一个类型的公共方法
using System.Reflection;
 
public class MyClass
{
       public MyClass()
       {}
       public void Method1()
       {}
       public static void Method2()
       {}
       protected void Method3()
       {}
       protected void Method4()
       {}
}
 
//客户端代码
Type type = typeof(MyClass);
 
MethodInfo[] methodInfoArray = type.GetMethods();
 
//跟踪所有的公共方法
foreach (MethodInfo methodInfo in methodInfoArray)
{
       Trace.WriteLine(methodInfo.Name);
}
 
//输出
GetHashCode
Equals
ToString
Method1
Method2
GetType
 
GetMethods()的另一个版本,接受一个参数,告知如何绑定到该类型:
public abstract MethodInfo[] GetMethods(BindingFlags bindingAttr);
 
BindingFlags枚举,指定:实例方法、静态方法、非公共方法等
 
取得方法的MethodInfo对象,就可以调用它,即使该方法是受保护的或是私有的:
public object Invoke(object obj, object[] parameters);
晚绑定调用
 
示例:使用反射调用对象的私有方法
using System.Reflection;
 
public class MyClass
{
       public MyClass()
       { ... }
       public void Method1()
       { ... }
      
       public void Method2()
       { ... }
 
       public static void Method5()
       { ... }
 
       protected void Method3()
       { ... }
 
       private void Method4()
       { ... }
}
 
//客户端代码
MyClass obj =- new MyClass();
Type type = typeof(MyClass);
 
MethodInfo[] methodInfoArray;
methodInfoArray = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
 
//仅调用私有方法
foreach (MethodInfo methodInfo in methodInfoArray)
{
       if (methodInfo.IsPrivate)
       {
              methodInfo.Invoke(obj, null);
}
}
 
GetMethod() ----------- MethodInfo
GetConstructors()、 GetConstructor() ------------------ ConstructorInfo
GetMember()、GetMembers()
GetEvent()、GetEvents()
 
属性
想法:可以用属性来修饰对象,而不需要通过编程实现各种功能和特性
 
属性本身是一个类,应该在名称中包含Attribute后缀,而且它必须派生于Attribute类:
 
public class FlagsAttribute : Attribute
{ ... }
 
如果属性名称是以Attribute结尾的,编译器允许省略Attribute后缀
[Flags]
public enum Color
{
       Red, Green, Blue, Purple = Red | Blue
}
 
每一个属性都有一个与它相关的 AttributeUsage类型的属性,它指明了该属性应该用于哪种类型(类、接口、枚举等),哪种语法元素(构造函数、方法、参数、返回值等)。
AttributeUsage也指定同一属性是否能在目标上使用多次
 
属性能够有一个默认的构造函数,并可以接受多个构造参数。如果有一个默认构造函数,可以使用带括号的属性,也可使用不带括号的属性。
[MyAttribute()]
 
属性种类
.NET有三种属性。
标准属性: 标准属性是 .NET 自带的, .NET 编译器和运行时知道这些属性并遵照它们的指示。
自定义属性 :自己提供的属性,除非编译器添加它们作为元数据的一部分,否则它们完全会被 .NET 忽略,你必须编写反射代码来使用自定义属性。这些属性经常包含具体问题域的定义
自定义上下文属性 :你和 .NET 都可以提供自定义上下文属性。 .NET 完全注意到它们,会遵从它们的指令并相应地影响修饰对象
 
实现自定义属性
示例:实现一个自定义属性
public enum ColorOption { Red, Green, Blue }
 
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface)]
public class ColorAttribute : Attribute
{
       ColorOption m_Color;
       public ColorOption Color
       {
              get
              {
                     return m_Color;
              }
              set
              {
                     m_Color = value;
              }
       }
 
       public ColorAttribute()
{
       Color = ColorOption.Red;
}
public ColorAttribute(ColorOption color)
{
       this.Color = color;
}
}
 
使用ColorAttribute自定义属性的例子:
使用默认构造函数
[Color]
public class MyClass1 {}
使用参数化构造函数
[Color(ColorOption.Green)]
public class MyClass2 {}
使用属性
[Color(Color=ColorOption.Blue)]
public class MyClass3 {}
在接口上使用
[Color]
public interface IMyInterface {}
 
AttributeUsageAttribute的定义:
public sealed class AttributeUsageAttribute : Attribute
{
       public AttributeUsageAttribute(AttributeTargets validOn);
       public bool AllowMultiple { get; set; }
       /* 其他成员 */
}
 
AttributeTargets枚举,指出这种属性可以在哪些类型上使用
另一个属性是AllowMultiple, 默认情况下,AllowMultiple的设置为false,你只能为每个类或接口使用一次属性,如果明确地设置AllowMultiple为true,你就能为同一个目标多次使用同一属性
 
反射自定义属性
示例:反射自定义属性
public static ColorOption GetColor(object obj)
{
       Type objType = obj.GetType();
       Debug.Assert(objType.IsClass || objType.IsInterface);
 
       Type attribute = typeof(ColorAttribute);
 
       object[] attributeArray = objType.GetCustomAttributes(attribType, true);
 
       //最多只有一个color属性
       Debug.Assert(attributeArray.Length == 0 || attributeArray.Length == 1);
 
       if (attributeArray.Length == 0)
       {
              return ColorOption.Red;
}
 
ColorAttribute colorAttribute = (ColorAttribute)attributeArray[0];
return colorAttribute.Color;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值