首先建立一个测试的类
public class MyClass
{
public int one { set; get; }
public int two { set; get; }
public int five { set; get; }
public int three { set; get; }
public int four { set; get; }
}
然后编写反射该类的代码
MyClass obj = new MyClass();
Type t = typeof(MyClass);
//循环赋值
int i = 0;
foreach (var item in t.GetProperties())
{
item.SetValue(obj, i, null);
i += 1;
}
//单独赋值
t.GetProperty("five").SetValue(obj, 11111111, null);
//循环获取
StringBuilder sb = new StringBuilder();
foreach (var item in t.GetProperties())
{
sb.Append("类型:" + item.PropertyType.FullName + " 属性名:" + item.Name + " 值:" + item.GetValue(obj, null) + "<br />");
}
//单独取值
int five = Convert.ToInt32(t.GetProperty("five").GetValue(obj, null));
sb.Append("单独取five的值:" + five);
string result = sb.ToString();
Response.Write(result);
测试显示结果:
类型:System.Int32 属性名:one 值:0
类型:System.Int32 属性名:two 值:1
类型:System.Int32 属性名:five 值:11111111
类型:System.Int32 属性名:three 值:3
类型:System.Int32 属性名:four 值:4
单独取five的值:11111111
好了,了解了类的属性反射使用后,聪明的你可能就想到了方法也是可以这样做的,即t.GetProperties()改为t.GetMethods(),操作方法同上。
1.加载程序集的几种方式
1.自动扫描当前运行项目的bin\debug ,网站是扫描bin目录 下的Lib.dll程序集 (常用)
1.Assembly.Load("Lib");
2.指定一个绝对路径加载程序集1.Assembly.LoadFile
2.Assembly.LoadFrom
3.获得当前 程序域中 所有的Assembly,包括GAC中的程序集1.AppDomain.CurrentDomain.GetAssemblies();
4.可以直接通过this来获取1.this.GetType().Assembly;
5. typeof(Form1).Assembly
2.获取类的几种方式
1.获取指定类的类型 ass.GetType("Lib.Pig");
2.获取当前所有的类(包括公有和非有) ass.GetTypes();
3.忽略类的全名的大小写 ass.GetType("Lib.pig", false, true);
4.可以typeof()关键字来获取 typeof(Form1);
5.可以通过实例的GetType()Type type5 = this.GetType(); Form1 f1 = new Form1(); Type type6 = f1.GetType();
3.操作类中的字段
1.获取私有字段
pigtype.GetField("_name", BindingFlags.NonPublic | BindingFlags.Instance);
BindingFlags.NonPublic | BindingFlags.Instance:表示获取一个非共有的实例字段,一定是组合使用
BindingFlags.NonPublic | BindingFlags.Static:表示获取一个非共有的静态字段 ,一定是组合使用
####2.给_name字段赋值
object instance = ass.CreateInstance("Lib.Pig");
nameInfo.SetValue(instance, "八戒");
3.获取instance中的_name字段值
object retVal = nameInfo.GetValue(instance);
MessageBox.Show(retVal.ToString());
4.操作类的方法
1.获取方法
pigType.GetMethod("Eat", BindingFlags.Public | BindingFlags.Instance);
2.调用方法
mInfo.Invoke(instance, new object[] { "八戒", 500 });
5.实例化对象
1. Assembly ass = Assembly.Load("Lib");
ass.CreateInstance("Lib.Pig");
2. Type pigType = ass.GetType("Lib.Pig");
Activator.CreateInstance(pigType);//要求:必须要求类拥有无参的构造函数,否则报错
3. ConstructorInfo cinfo = pigType.GetConstructor(new Type[] { typeof(string) });
object pigInstance = cinfo.Invoke(new object[] { "八戒11" }); //new Pig("八戒",500)
4. /获取pigInstance中的Name的值
PropertyInfo nameInfo = pigType.GetProperty("Name");
object res = nameInfo.GetValue(pigInstance)
6.Type类型中重要方法
Assembly ass = Assembly.Load("Lib");
Type pigType = ass.GetType("Lib.Pig");
//获取程序集的绝对路径
//pigType.Assembly.Location
//pigType .FullName //Lib.Pig
//pigType.Name// Pig
//1.0 判断Pig类是否实现了Ipig接口
//1.0.1 获取IPig接口的Type
Type ipigType = ass.GetType("Lib.IPig");
//1.0.2 判断pigType是否实现了ipigType
bool isok = ipigType.IsAssignableFrom(pigType); //true
//2.0 判断Pig类是否继承了Basepig类
Type basepigType = ass.GetType("Lib.BasePig");
bool isext = pigType.IsSubclassOf(basepigType); //true
//3.0 object instance=new Pig();
object instance = ass.CreateInstance("Lib.Pig");
pigType.IsInstanceOfType(instance); //true
如果在一个类中有一个公有字段,那么在这个类的外部我们可以*无阻的使用这个字段,但是如果给这个字段赋了一个很“离谱”的值,那这对程序可能会造成很大的影响
比如:
Class Student{
public int Age;
}
在这个类外我们写:
Student stu =new Student();
stu.Age = 1000;
众所周知,人目前是不可能活到1000岁的,但是这样赋值编译器又不会报错(假设外部没有限制Age取值的逻辑),但是我们知道这个程序运行后的结果是有错误的
所以我们有了“属性”这个东西,代码可以这样写:
class
Student
{
private
int
age;
public
int
Age
{
get
{
return
age; }
set
{
if
(value >= 0 && value <= 100)
{
age = value;
}
else
{
throw
new
Exception(
"Age value has error."
);
}
}
}
这里的value以为上下文关键字了
属性里的get,set访问器可以对字段提供一些安全保护了(个人理解为使用一些逻辑来保护字段的值为“说的过去的”)
---------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------
一段总结:
//属性对外:暴露数据,数据可以是存储在字段里的,也可以是动态计算出来的
//对内:保护字段不受“非法值”污染
//一般情况下,它们都用于表示实体(对象或类型)的状态
//属性大多数情况下是字段的包装器(wrapper)
//建议:永远使用属性(而不是字段)来暴露数据,即字段永远是private或protected的