反射的概念
反射是.net提供的一个强大的功能机制,可以在运行时,动态的更改操作对象的类型。通过使用反射,程序可以动态的创建对象,使用方法,访问字段等
反射的应用
反射的应用很广泛,包括动态类型创建、动态方法调用、属性访问、自定义属性处理等。
我们可以根据反射的对象不同,分为两类:字段反射和方法反射。
1 获取类型信息 名称,基类,接口等
Type type = typeof(Cat);
Console.WriteLine(type.Name);//Cat
2 创建对象实例
Type type = typeof(Cat);
object instance = Activator.CreateInstance(type); // 创建 Cat 的实例
下边的Persons对象
public class Persons
{
public string Name { get; set; }public int GetAge(int year)
{
var curYear = DateTime.Now.Year;
return curYear - year;
}public string Action<T>(T str)
{
return str.ToString();
}
}
3 字段反射
假设有一个Person类,我们想更新字段值
public async static Task<string> GetPerson()
{
Persons per = new Persons();
Type perType = typeof(Persons);var fieldName = "Name";
// 获取User类的Name字段
var fieldInfo = perType.GetField(fieldName);// 设置User实例的Name字段值
fieldInfo.SetValue(per, "Jieke");return per.Name;
}
4 方法反射
public async static Task<string> GetAge()
{
Persons per = new Persons();
Type perType = typeof(Persons);// 获取GetAge方法的信息
var methodInfo = perType.GetMethod("GetAge");// 动态调用GetAge方法
object[] parameters = new object[] { 2022 };
var result = methodInfo.Invoke(per, parameters);return result.ToString();
}
5 泛型方法反射
public async static Task<string> GetAction()
{
Persons per = new Persons();
Type perType = typeof(Persons);
// 获取Action方法的信息
var methodInfo = perType.GetMethod("Action").MakeGenericMethod(new Type[] { typeof(string) });
// 调用泛型方法
var res = methodInfo.Invoke(per, new object[] { "Hello, Generic Reflection!" });
return res.ToString();
}
除了这些常用此外,还有其他的反射用法,需要的可以自行了解
如果现在有一个这样的简单场景,我们可以结合泛型和反射来使用
现在要写一个帮助类,遇到一个问题,根据传入对象的不同,返回不同的类型。这个一开始想着很简单,可以使用泛型T解决,但是后边发现很多if分支,导致代码维护很麻烦,于是我想起来有反射
private static ResultModel GetConnect<T>(List<string> AppUrls, ref T WoConnecting, string RefType)
{
ResultModel rm = new ResultModel();
try
{
// ESUN_WMS_DWH.WMS_DWH
foreach (var url in AppUrls)
{
if (EsunWoConnecting == null)
{
try
{
SerilogHelper.WriteLog("GetConnect" + RefType, "url", url.ToString());
if (RefType.ToString().ToLower() == RefTypeEnum.WMSDWH.ToString().ToLower())
{
EsunWoConnecting = (T)(object)new WMS_DWH(new Connection(url, "", "", ""));
}
else if (RefType.ToString().ToLower() == RefTypeEnum.MRSDWH.ToString().ToLower())
{
WoConnecting = (T)(object)new MRSDWH(new Connection(url, "", "", ""));
}
else if (RefType.ToString().ToLower() == RefTypeEnum.MRSWMS.ToString().ToLower())
{
WoConnecting = (T)(object)new MRSWMS(new Connection(url, "", "", ""));
}
if (WoConnecting != null)
{
return rm;
}
}
catch (Exception ex)
{
SerilogHelper.WriteLog("GetConnect" + RefType, "ex"+ex.Message);
continue;
}
}
}
}
catch (Exception ex)
{
rm.ResultCode = "100001";
rm.ResultMsg = ex.Message;
SerilogHelper.WriteLog("GetConnect" + RefType, "ex"+ex.Message);
}
return rm;
}
当我使用反射之后
private static ResultModel GetConnect<T>(List<string> AppUrls, ref T WoConnecting)
{
ResultModel rm = new ResultModel();
try
{
// ESUN_WMS_DWH.WMS_DWH
foreach (var url in AppUrls)
{
if (WoConnecting == null)
{
try
{
SerilogHelper.WriteLog("GetConnect" + typeof(T).GetCString(), "url", url.GetCString());//使用反射创建
WoConnecting = (T)Activator.CreateInstance(typeof(T), new Connection(url, "", "", ""));
if (WoConnecting != null)
{
return rm;
}
}
catch (Exception ex)
{
SerilogHelper.WriteLog("GetConnect" + typeof(T).GetCString(), "ex" + ex.Message);
continue;
}
}
}
}
catch (Exception ex)
{
rm.ResultCode = "100001";
rm.ResultMsg = ex.Message;
SerilogHelper.WriteLog("GetConnect" + typeof(T).GetCString(), "ex" + ex.Message);
}
return rm;
}
由此可以看到反射用处还是很多的,了解和掌握反射的使用可以帮助开发者编写更加灵活和强大的.NET应用程序。它提供了一种在运行时查询和操作类型信息的能力,通过反射,我们可以动态地创建对象、调用方法、访问字段和属性,这为编写灵活和动态的代码提供了极大的便利。
尽管反射提供了强大的功能,但它也有一些缺点。反射操作通常比直接代码调用要慢,因为它需要在运行时解析类型信息。此外,过度使用反射可能会使代码变得难以理解和维护。因此,我们应该谨慎使用,在使用反射时应该权衡其给项目带来的好处和成本,避免不必要的性能开销和复杂性增加。