什么是元数据,什么是反射
- 程序是用来处理数据的,文本和特性都是数据,然而程序本身也是数据
- 有关程序及其类型的数据被称为元数据(metadata),他们保存在程序的程序集中
- 程序在运行时,可以查看其他程序集或者本身的元数据。一个运行的程序查看本身的元数据或者其他程序集的元数据的行为叫做反射
Type类
- 预定义类型(int long string等)BLC中的类型(Console,IEnumerable等)和程序员自定义类型(MyClass,MyDel等),每种类型都有自己的成员和特性。
- Type是一个抽象类,他被设计用来包含类型的特性,使用这个类的对象能让我们获取程序使用的类型和信息
- Type是抽象类 ,所以不能利用他去实例化对象
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace _002_反射
{
class Program
{
static void Main(string[] args)
{
//每一个类对应一个type对象,,这个对象存储了这个类,有哪些方法,成员
Text mytext = new Text(); //类中的数据是存储在对象中的,type之存储类的成员
//通过对象获取对象所属类的Type的对象
Type type = mytext.GetType();
Console.WriteLine(type.Name); //获取类名
Console.WriteLine(type.Namespace); //所在命名空间
Console.WriteLine(type.Assembly); //程序集
//获取方法中所有公有的(public)字段
Console.WriteLine();
Console.WriteLine("========公有字段=========");
FieldInfo[] infoarr = type.GetFields();
foreach (FieldInfo item in infoarr)
{
Console.Write(item.Name + " ");
}
//获取所有的公有属性
Console.WriteLine();
Console.WriteLine("========公有属性=========");
PropertyInfo[] properarr = type.GetProperties();
foreach (PropertyInfo info in properarr)
{
Console.Write(info.Name + " ");
}
//获取所有的公有方法
Console.WriteLine();
Console.WriteLine("========公有方法=========");
MethodInfo[] methodarr = type.GetMethods();
foreach (MethodInfo info in methodarr)
{
Console.Write(info.Name + " ");
}
Console.ReadKey();
}
}
}
namespace _002_反射
{
class Text
{
private int id;
public int age;
public int num;
public string Name { get; set; }
public string Age { get; set; }
public string Sex { get; set; }
public void Test1() {}
public void Text2() { }
}
}
运行结果:
Assembly类
Assembly 类: (Text类使用的还是上面的那个)
如何加载程序集?
- Assembly assembly1 =Assembly.Load(“SomeAssembly”);根据程序集的名字加载程序集,它会在本地目录和全局程序集缓存目录查找符合名字的程序集。
- Assembly assembly2 =Assembly.LoadFrom(@”c:\xx\xx\xx\SomeAssembly.dll”)//这里的参数是程序集的完整路径名,它不会在其他位置搜索。
using System;
using System.Reflection;
namespace _002_反射
{
class Program
{
static void Main(string[] args)
{
Text mytext = new Text();
//通过类的type对象获取它所在的程序集
Assembly assem = mytext.GetType().Assembly;
Console.WriteLine("完整的名字:"+ assem.FullName);
Type[] type = assem.GetTypes();
foreach (var item in type)
{
Console.WriteLine(item);
}
//源码编译就会出来.exe文件和一些配置文件,即程序集,,
Console.ReadKey();
}
}
}
特性Attrbute
特性是一种允许我们向程序的程序集中增加元数据的语言结构。他是用于保存程序信息的某种特殊类型的类
我们将应用了特性的程序结构叫做目标
设计用来获取和使用元数据的程序叫做特性的消费者
Obsolete特性,通过这个特性表示一个方法已经被弃用了,(但是还能使用下面会有波浪线做标识)
[ Obsolete]示例
namespace _003_特性
{
class Program
{
static void Main(string[] args)
{
// 当 [Obsolete ("此方法已过时,请使用NewFun"),ture] 调用会出编译错误
// OldFun();
//若不写第二个参数,,则会画波浪线做出提示,且方法可用
OldFun();
}
//通过这个特性表示一个方法已经被弃用了,(但是还能使用下面会有波浪线做标识)
[Obsolete ("此方法已过时,请使用NewFun")]
static void OldFun()
{
Console.WriteLine("OldFun");
}
static void NewFun()
{
Console.WriteLine("NewFun");
}
}
}
Conditional特性允许我们包括或取消特定方法的所有调用。为方法声明应用Conditional特性并把编译符作为参数来使用。 定义方法的CIL代码本身总是会包含在程序集中,只是调用代码会被插入或忽略。
//##########################注意这里,只有在这里定义这个字段,方法才能调用
#define Method1
using System;
using System.Diagnostics; //命名空间
namespace _003_特性
{
class Program
{
static void Main(string[] args)
{
//模拟多次调用方法,,,如果想取消调用method1() 就会变得麻烦
Method1();
Method2();
Method1();
Console.ReadKey();
}
[Conditional("Method1")]
static void Method1()
{
Console.WriteLine("Method1");
}
static void Method2()
{
Console.WriteLine("Method2");
}
}
}
调用者信息特性可以访问文件路径,代码行数,调用成员的名称等源代码信息。
1.这个三个特性名称为CallerFilePath,CallerLineNumber和CallerMemberName
2.这些特性只能用于方法中的可选参数
using System;
using System.Runtime.CompilerServices;
namespace _003_特性
{
class Program
{
static void Main(string[] args)
{
DebugLog("Czhenya");
Console.ReadKey();
}
static void DebugLog(string str,[CallerFilePath]string fileName = "",
[CallerLineNumber]int lineNumber = 0,
[CallerMemberName]string methodName = "")
{
Console.WriteLine("用户输入的参数:"+str);
Console.WriteLine("调用的目录:"+fileName);
Console.WriteLine("在第{0}行调用的",lineNumber);
Console.WriteLine("在{0}方法中调用的",methodName);
}
}
}
自定义特性类
- 特性类必须继承System.Attribute
- 类名需要以Attribute结尾
- 一般声明为sealed
- 一般情况下特性类用来表示目标结构的一些状态,定义一些字段,属性,不定义方法
using System;
namespace _003_特性
{
// 特性类,后缀以Attribute结尾
// 需要继承自System.Attibute
// 一般声明为sealed
// 一般情况下特性类用来表示目标结构的一些状态,定义一些字段,属性,不定义方法
[AttributeUsage(AttributeTargets.Class)] //表示该特性类可以使用的结构有哪些
sealed class MyAttribute : Attribute
{
public string Desctiption { get; set; }
public string VersionNumber { get; set; }
public int ID { get; set; }
//构造函数
public MyAttribute(string str)
{
this.Desctiption = str;
}
}
}
using System;
namespace _003_特性
{
//通过制定属性的名字,给属性赋值,这种就是命名参数
[My("简单的特性类", ID=100)] //使用特性的时候,后面的Attribute不用写
class Program
{
static void Main(string[] args)
{
//通过typeof(类名) 也可创建type对象
Type type = typeof(Program);
object[] objarr = type.GetCustomAttributes(false);
//获取本类使用到的特性
MyAttribute my = objarr[0] as MyAttribute;
Console.WriteLine(my.Desctiption+"\n ID : "+my.ID);
Console.ReadKey();
}
}
}
作者:Czhenya
来源:CSDN
原文:https://blog.csdn.net/czhenya/article/details/78328986
版权声明:本文为博主原创文章,转载请附上博文链接!