本文档写的的是C#中的反射常用的方式(附带示例代码)以及在使用的时候的一些注意事项。
C#中的反射是一种强大的机制,它允许在运行时动态地检查、访问和操作程序的元数据、类型信息和对象。以下是C#中反射常用的技巧和使用方式:
字段没有get与set访问器
public class MyClass
{
private int myField; // 字段
public int MyProperty // 属性
{
get { return myField; }
set { myField = value; }
}
}
type.GetFields();
,type.GetField(name)
type.GetProperties()
, type.GetProperty(name)
type.GetMethods()
,type.GetMethod(name)
type.GetInterfaces()
using System.Reflection;
DateTime beforDT = System.DateTime.Now;
FanShe();
DateTime afterDT = System.DateTime.Now;
TimeSpan ts = afterDT.Subtract(beforDT);
Console.WriteLine("DateTime总共花费{0}ms.", ts.TotalMilliseconds);
Console.ReadKey();
static void FanShe()
{
//创建对象
Man manObj = new Man();
Type type = manObj.GetType();
//获取所有字段
Console.WriteLine("\n获取公开的字段");
FieldInfo[] fieldInfos = type.GetFields();
for (int f = 0; f < fieldInfos.Count(); f++)
{
Console.WriteLine("公开的字段有:" + fieldInfos[f].Name);
}
Console.WriteLine("\n获取特定字段并修改字段:");
//字段与属性的区别,字段无getset访问器,属性有。
FieldInfo fieldInfo_id = type.GetField(nameof(Animal.Age));
fieldInfo_id.SetValue(manObj, 123);//设置Age为123
Console.WriteLine("第一次修改是age字段是:" + fieldInfo_id.GetValue(manObj));//打印出Age
fieldInfo_id.SetValue(manObj, 17);//设置Age为123
Console.WriteLine("第二次修改是age字段是:" + fieldInfo_id.GetValue(manObj));//打印出Age
Console.WriteLine("\n所有属性:");
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
Console.WriteLine(property.Name);
}
Console.WriteLine("\n获取特定属性并修改属性");
PropertyInfo propertie_name = type.GetProperty(nameof(Man.Nationality));
propertie_name.SetValue(manObj, "China");
Console.WriteLine("第一次修改后的属性是" + propertie_name.GetValue(manObj));
propertie_name.SetValue(manObj, "Japan");
Console.WriteLine("第二次修改后的属性是" + propertie_name.GetValue(manObj));
Console.WriteLine("/n获取实现的接口");
Type[] interfaces = type.GetInterfaces();
foreach (Type iface in interfaces)
{
Console.WriteLine(iface.Name);
}
Console.WriteLine("是否为空的判断");
if (type.GetProperty(nameof(Man.Colour)) == null)
{
Console.WriteLine($"{nameof(Man.Colour)}not found.");
return;
}
PropertyInfo manColour = type.GetProperty(nameof(Man.Colour));
if (!manColour.CanWrite)
{
Console.WriteLine("Cannot write to Man.Colour property.");
return;
}
manColour.SetValue(manObj, "yellow");//设置属性
Console.WriteLine($"{nameof(manObj.Colour)}:{manObj.Colour}");
//获取到公开的方法
MethodInfo[] methodInfos = type.GetMethods();
for (int i = 0; i < methodInfos.Count(); i++)
{
Console.WriteLine(methodInfos[i].Name);
}
Console.WriteLine("\n调用无参的方法");
MethodInfo methodInfo_popop = type.GetMethod(nameof(Man.Popop));
methodInfo_popop.Invoke(manObj, null);
Console.WriteLine("\n调用有参的方法");
MethodInfo methodInfo_eatFood = type.GetMethod(nameof(Man.EatFood));
methodInfo_eatFood.Invoke(manObj, new object[] { "香蕉", 123 });
Console.WriteLine("\n调用无参数有返回值的方法");
MethodInfo methodInfo_Speed = type.GetMethod(nameof(Man.Speed));
object money = methodInfo_Speed.Invoke(manObj, new object[] { 123 });
Console.WriteLine($"反射方法的返回值是:{money}");
Console.WriteLine("\n调用接口无返回值无参数");
MethodInfo speakingEnglishMethod = type.GetInterface(nameof(ILanguage)).GetMethod(nameof(Animal.SpeakingEnglish));
speakingEnglishMethod.Invoke(manObj, null); // 输出: I can speak English.
Console.WriteLine("\n调用接口无返回值有参数");
MethodInfo speakJapaneseMethod = type.GetInterface(nameof(ILanguage)).GetMethod(nameof(Animal.SpeakJapanese));
Console.WriteLine("返回是:" + "返回值是:" + speakJapaneseMethod.Invoke(manObj, null));
Console.WriteLine("\n调用接口有返回值有参数");
MethodInfo speakChineseMethod = type.GetInterface(nameof(ILanguage)).GetMethod(nameof(Animal.SpeakChinese));
Console.WriteLine("返回值是:" + speakChineseMethod.Invoke(manObj, new object[] { "你好" }));
Console.WriteLine("\n当与父类中有相同的方法的时候,调用父类中的同名方法");
MethodInfo animalDoSexMethod = type.BaseType.GetMethod(nameof(Animal.DoSex));
Console.WriteLine("父类中的方法" + animalDoSexMethod.Invoke(manObj, new object[] { "hei heihei" }));
Console.WriteLine("\n当与父类中有相同的方法的时候,调用子类的同名方法");
MethodInfo manDoSexMethod = type.GetMethod(nameof(Man.DoSex));
Console.WriteLine("子类中的方法" + manDoSexMethod.Invoke(manObj, new object[] { "ha hhhaa" }));
Console.WriteLine("\n子类调用重写的方法,\n当子类重写了父类的方法时,您可以通过子类类型来反射调用它。但是需要注意的是,在这种情况下,将始终调用子类中的方法版本,而不是父类中的版本。");
MethodInfo drawMethod = type.GetMethod(nameof(Man.Draw));
drawMethod.Invoke(manObj, new object[] { "山水" });
}
public class Man : Animal, ILanguage
{
///
/// 国籍
///
public string Nationality { get; set; }
///
/// 肤色
///
public string Colour { get; set; }
///
/// 瞳孔颜色
///
public string PupilColor;
///
/// 说话
///
///
public void Say(string word)
{
Console.WriteLine("我说:" + word);
}
///
/// 花钱
///
public int Speed(int money)
{
Console.WriteLine($"本次消费的金额是:{money}元。");
return money;
}
///
/// 读书
///
private void ReadBook()
{
Console.WriteLine("Reading book");
}
///
/// 交配
///
///
public new string DoSex(string targetName)
{
return $"is sexing with {targetName} ";
}
///
/// 画画
///
///
public override void Draw(string drawName)
{
Console.WriteLine($"这副{drawName}被我画好了");
}
}
///
/// 动物
///
public class Animal : ILanguage
{
///
/// 序号
///
public int ID { get; set; }
///
/// 姓名
///
public string Name { get; set; }
///
/// 性别
///
public string Sex;
///
/// 年龄
///
public int Age;
///
/// 是否开心
///
public bool isHappy;
///
/// 吃饭
///
///
///
public void EatFood(string foodName, int foodcount)
{
Console.WriteLine($"我吃了{foodcount}个{foodName}");
}
///
/// 拉屎
///
///
public string Popop()
{
Console.WriteLine("is popoping");
return "poping";
}
///
/// 交配
///
///
public string DoSex(string targetName)
{
return $"is sexing with {targetName} ";
}
public void SpeakingEnglish()
{
Console.WriteLine("i am speaking English, no return value and parameters.");
}
public string SpeakJapanese()
{
return "Speaking Japanese wrod";
}
public string SpeakChinese(string wrod)
{
return $"Chinese wrod:{wrod}";
}
///
/// 画画
///
///
public virtual void Draw(string drawName)
{
Console.WriteLine($"我正在画{drawName}");
}
}
///
/// 语言的接口
///
public interface ILanguage
{
///
/// 说英语
///
void SpeakingEnglish();
string SpeakJapanese();
string SpeakChinese(string wrod);
}