#define DEBUG_MODE
using System;
using System.Reflection;
using System.Diagnostics;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//C# 特性(Attribute)
/*
* 特性(Attribute)是用于在运行时传递程序中的各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([])来描述的。
* 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net框架提供了两种类型的特性:预定义特性和自定义特性
*
* 规定特性(Attribute)
* 语法:[attribute(positional_parameters, name_parameter = value, ...)] element
* positional_parameters规定必须的信息
* name_parameter规定可选的信息
*
* 预定义特性(Attribute)
* .Net框架提供了三种预定义特性:
* 1.AttributeUsage
* 2.Conditional
* 3.Obsolete
*
* AttributeUsage:描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。
* [AttributeUsage(
* validon,
* AllowMultiple allowmultiple,
* Inherited inherited
* )]
* 其中:
* validon规定特性可被放置的语言元素。它是枚举器AttributeTargets的值的组合。默认是AttributeTargets.All
* allowmultiple(可选的)为该特性的AllowMultiple属性(property)提供一个布尔值。如果为true,则该特性是多用的。默认值是false(单用的)。
* inherited(可选的)为该特性的Inherited属性(property)提供一个布尔值。如果为true,则该特性可以被派生类继承。默认值为false(不被继承)。
*
* 例如:
* [AttributeUsage(AttributeTargets.Class |
* AttributeTargets.Constructor |
* AttributeTargets.Field |
* AttributeTargets.Method |
* AttributeTargets.Property,
* AllowMultiple = true)]
*
* Conditional
* 这个预定义特性标注了一个条件方法,其执行依赖于指定的预处理标识符
* 他会引起方法调用的条件编译,取决于指定值,比如Debug或Trace。例如,当调试代码时显示变量的值。
* 语法:
* [Conditional(
* conditionalSymbol
* )]
* 例如:
* [Conditional("DEBUG")]
*/
//实例
MyClass.Message("in main func");
func1();
//Obsolete
//这个预定义特性标记了不应被使用的程序实体。它可以让您通知编辑器丢弃某个特定的目标元素。例如:当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为obsolete(过时的)
/*语法:
* [Obsolete(
* message
* )]
* [Obsolete(
* message,
* iserror
* )]
* 其中:
* message是一个字符串,描述项目为什么过时以及该替代使用什么
* iserror是一个布尔值,如果该值为true,编译器应把该项目的使用当作一个错误。默认值false(编译器生成一个警告)
*/
//实例
//OldMethod();
//创建自定义特性(Attribute)
/*
* .net框架允许创建自定义特性,用于存储声明性的信息,且可在运行时被检索。该信息根据设计标准和应用程序需要,可与任何目标元素相关
* 创建并使用自定义特性包含四个步骤
* 声明自定义特性->构建自定义特性->在目标程序元素上应用自定义特性->通过反射访问特性
* 最后一个步骤是编写程序来读取元数据以查找各种符号。元数据是用于描述其他数据的数据和信息。该程序应使用反射来在运行时访问特性。
*
* 声明自定义特性
* 一个新的自定义特性应派生自System.Attribute类
* //一个自定义特性BugFix被赋给类及其成员
* [AttributeUsage(AttributeTargets.Class |
* AttributeTargets.Constructor |
* AttributeTargets.Field |
* AttributeTargets.Method |
* AttributeTargets.Property,
* AllowMultiple = true
* )]
* public class DeBugInfo: System.Attribute
*
* 构建自定义特性
* 该特性将存储调试程序获得的信息,它存储以下信息:
* bug的代码编号
* 辨认该bug的开发人员名字
* 最后一次审查该代码的日期
* 一个存储了开发人员标记的字符串消息
*
* 我们的DeBugInfo类将带有3个用于存储前3个信息的私有属性(property)和一个用于存储消息的公有属性(property)。所以bug编号、开发人员的名字和审查日期将是DeBugInfo类必须的定位(positional)参数,消息将是一个可选的命名(named)参数。
* 每个特性必须至少有一个构造函数。必需的定位(positional)参数应通过构造函数传递。
*
* 见下DeBugInfo类
*
*
* 应用自定义特性
* 通过把特性放置在紧接着它的目标之前,来应用特性
*
* 见下Rectangle类
*/
//反射
/*
* 反射指程序可以访问、检测和修改它本身状态或行为的一种能力
* 程序集包含模块,而模块包含类型,类型又包含成员。反射则提供了封装程序集、模块和类型的对象。
* 你可以使用反射动态的创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型。然后,调用类型的方法或访问其字段和属性。
*
* 优点:
* 1.反射提高了程序的灵活性和扩展性
* 2.降低耦合性,提高自适应能力
* 3.它允许程序创建和控制任何类的对象,无需提前硬编码目标类
* 缺点:
* 1.性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,普通程序不建议使用。
* 2.使用反射会模糊程序内部的逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术,因此会带来维护问题,反射代码比相应的直接代码更复杂。
*
*
* 反射(reflection)的用途
* 1.它允许在运行时查看特性(attribute)信息
* 2.它允许审查集合中的各种类型,以及实例化这些类型
* 3.它允许延时绑定的方法和属性(property)
* 4.它允许在运行时创建新类型,然后使用这些类型执行一些任务
*
*
* 查看元数据
* 使用反射可以查看特性信息
* System.Reflection类的MemberInfo对象需要被初始化,用于发现与类相关的特性(attribute)。\
* System.Reflection.MemberInfo info = typeof(MyClass);
*
*/
System.Reflection.MemberInfo info = typeof(MyClass2);
object[] attributes = info.GetCustomAttributes(true);
for(int i = 0;i<attributes.Length;i++)
{
Console.WriteLine(attributes[i]);
}
//获取Rectangle上的DeBugInfo信息
Rectangle r = new Rectangle(4.5, 7.5);
r.Display();
Type type = typeof(Rectangle);
//遍历Rectangle类的特性
foreach(Object attributes2 in type.GetCustomAttributes(false))
{
DeBugInfo dbi = (DeBugInfo)attributes2;
if(null != dbi)
{
Console.WriteLine("Bug no: {0}", dbi.BugNo);
Console.WriteLine("Developer: {0}", dbi.Developer);
Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
Console.WriteLine("Remarks: {0}", dbi.Message);
}
}
//遍历方法特性
foreach(MethodInfo mi in type.GetMethods())
{
foreach(Attribute ai in mi.GetCustomAttributes(true))
{
DeBugInfo dbi = (DeBugInfo)ai;
if (null != dbi)
{
Console.WriteLine("Bug no: {0}", dbi.BugNo);
Console.WriteLine("Developer: {0}", dbi.Developer);
Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
Console.WriteLine("Remarks: {0}", dbi.Message);
}
}
}
Console.ReadKey();
}
[Obsolete("Don't use OldMethod, use NewMethod instead", true)]
static void OldMethod()
{
Console.WriteLine("It is the old method.");
}
static void NewMethod()
{
Console.WriteLine("It is the new method.");
}
static void func1()
{
MyClass.Message("in func1.");
func2();
}
static void func2()
{
MyClass.Message("in func2.");
}
}
[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute: System.Attribute
{
public readonly string Url;
public string Topic//Topic是一个命名(named)参数
{
get
{
return topic;
}
set
{
topic = value;
}
}
public HelpAttribute(string url) //url是一个定位(positional)参数
{
this.Url = url;
}
private string topic;
}
[HelpAttribute("Information on the class MyClass2")]
class MyClass2
{
}
[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle
{
//成员变量
protected double length;
protected double width;
public Rectangle(double l, double w)
{
length = l;
width = w;
}
[DeBugInfo(55, "Zara Ali", "19/10/2012", Message ="Return type mismatch")]
public double GetArea()
{
return length * width;
}
[DeBugInfo(56, "Zara Ali", "19/10/2012")]
public void Display()
{
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
//一个自定义特性BugFix被赋给类及其成员
[AttributeUsage(AttributeTargets.Class |
AttributeTargets.Constructor |
AttributeTargets.Field |
AttributeTargets.Method |
AttributeTargets.Property,
AllowMultiple = true)]
public class DeBugInfo : System.Attribute
{
private int bugNo;
private string developer;
private string lastReview;
private string message;
public DeBugInfo(int b, string dev, string d)
{
this.bugNo = b;
this.developer = dev;
this.lastReview = d;
}
public int BugNo
{
get
{
return bugNo;
}
}
public string Developer
{
get
{
return developer;
}
}
public string LastReview
{
get
{
return lastReview;
}
}
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
public class MyClass
{
//message only show on DEBUG_MODE
[Conditional("DEBUG_MODE")]
public static void Message(string msg)
{
Console.WriteLine(msg);
}
}
}