C# 反射

反射的概念

反射是.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应用程序。它提供了一种在运行时查询和操作类型信息的能力,通过反射,我们可以动态地创建对象、调用方法、访问字段和属性,这为编写灵活和动态的代码提供了极大的便利。

尽管反射提供了强大的功能,但它也有一些缺点。反射操作通常比直接代码调用要慢,因为它需要在运行时解析类型信息。此外,过度使用反射可能会使代码变得难以理解和维护。因此,我们应该谨慎使用,在使用反射时应该权衡其给项目带来的好处和成本,避免不必要的性能开销和复杂性增加。

  • 19
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值