程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 反射(Reflection)的用途剖析

C# 反射(Reflection)的用途剖析

編輯:C#入門知識

C# 反射(Reflection)的用途剖析。本站提示廣大學習愛好者:(C# 反射(Reflection)的用途剖析)文章只能為提供參考,不一定能成為您想要的結果。以下是C# 反射(Reflection)的用途剖析正文


亂侃

       作為一位老手,一向沒有勇氣去寫一篇分享。緣由有許多:諸如:本身程度無限、說話表達禁絕確、寫出的器械沒有一點技巧點被人譏笑。明天在公司聽了外部員工的一個分享,個中最主要的一點是:晉升本身程度的最好的門路就是——交換。不論你是經由過程甚麼門路,交換也好、整頓成文字分享也好等等都是很好的方法。故此,明天獻丑寫一篇本身的心得分享,迎接各路年夜神的指教!

   需求配景

     明天接到的需求外面有個如許的需求,以下圖所示,須要打印出如Excel內容出現的單據。

    著手操作初版本

     而為了完成這個營業須要觸及三張表的數據。(寄存單據的表、審核看法表、審核狀況表)
     三張表的關系:單據表1:1審核狀況表,單據表1:N審核看法表
     為了完成讓View頁面整潔,我界說了一個SpecialPrintModel類

public class SpecialPrintModel
  {
    /// <summary>
    /// 供給商承當
    /// </summary>
    public string SupplierUnderTaker { get; set; }

    /// <summary>
    /// 客戶定單號
    /// </summary>
    public string CustomerSerialNumber { get; set; }
    
    /// <summary>
    /// 付款金額
    /// </summary>
    public decimal PayAmount { get; set; }

    /// <summary>
    /// 開戶行
    /// </summary>
    public string OpeningBank { get; set; }

    /// <summary>
    /// 收款單元
    /// </summary>
    public string CollectionMonad { get; set; }

    /// <summary>
    /// 銀行帳號
    /// </summary>
    public string BankAccount { get; set; }

    /// <summary>
    /// 經辦人
    /// </summary>
    public string ResponseiblePerson { get; set; }

    /// <summary>
    /// 分擔引導
    /// </summary>
    public string Leader { get; set; }

    /// <summary>
    /// 財政審核
    /// </summary>
    public string FinanceApproval { get; set; }

    /// <summary>
    /// 財政司理審核
    /// </summary>
    public string FinanceManagerApproval { get; set; }

    /// <summary>
    /// 財政總監審核
    /// </summary>
    public string FinanceDirectorApproval { get; set; }

    /// <summary>
    /// CEO審核
    /// </summary>
    public string CEOApproval { get; set; }

    /// <summary>
    /// 流水號
    /// </summary>
    public string SerialNumber { get; set; }
  }
public List<ShipSpecialPrintModel> GetTobePaidRecepit(ShipSpecialSearch search)
 {
   List<ShipSpecialPrintModel> curiseShipModel = new List<ShipSpecialPrintModel>();
   var toBePaidModel = persistant.GetTobePaidRecepit(search);//查找出待付出的單據表信息
   ArrayList serialArray=new ArrayList();//界說一個流水號列表
   toBePaidModel.ForEach((u) => { serialArr.Add(u.SerialNumber); });
   var toBePaidComment = persistant.GetTobePaidRecepitComment(serialArr);//查找出待付出單據的審核看法表(1個單據對應若干審核看法)
   foreach (var item in toBePaidModel)
   {
     ShipSpecialPrintModel temp = new ShipSpecialPrintModel()
     {
         SupplierUnderTaker = supplierUnderTaker;
         CustomerSerialNumber = item.CustomerOrderNumber;
         PayAmount = item.PayAmount;
         OpeningBank = item.PayBank;
         CollectionMonad = item.Payee;
         ResponseiblePerson = item.Creator;
         SerialNumber = item.SerialNumber;
     };
     curiseShipModel.Add(temp);
   }
    foreach (var curise in curiseShipModel)
      {
        foreach (var comment in toBePaidComment)
        {
          if (comment.SerialNumber == curise.SerialNumber)
          {
            if (comment.ApprovalLevel == (int)LevelType.BranchedLeader)
            {
              curise.Leader = comment.Creator;
            }
            else if (comment.ApprovalLevel == (int)LevelType.Finance)
            {
              curise.FinanceApproval = comment.Creator;
            }
            else if (comment.ApprovalLevel == (int)LevelType.FinanceManager)
            {
              curise.FinanceManagerApproval = comment.Creator;
            }
            else if (comment.ApprovalLevel == (int)LevelType.ProjectDirector)
            {
              curise.FinanceDirectorApproval = comment.Creator;
            }
            else if (comment.ApprovalLevel == (int)LevelType.CEO)
            {
              curise.CEOApproval = comment.Creator;
            }
          }
        }
      }

   return curiseShipModel
 }

    呵呵,下面的代碼根本完成了營業的需求,可是假如營業須要打印出CTO的稱號、CIO的稱號那在if else這邊加,固然很簡略然則違反了開放-關閉的准繩。故自己決議用反射去完成這if...else的工作。
由於if...else外面的斷定是以後的這筆單據的審核看法表的層級是否是跟SpecialPrintModel的字段所對應的層級相等,若相等則在對應字段寫入絕對應的稱號。決議把SpecialPrintModel這個類修正下。
 
   著手操作第二版本

public class ShipSpecialPrintModel
  {
    /// <summary>
    /// 供給商承當
    /// </summary>
    public string SupplierUnderTaker { get; set; }

    /// <summary>
    /// 客戶定單號
    /// </summary>
    public string CustomerSerialNumber { get; set; }
    
    /// <summary>
    /// 付款金額
    /// </summary>
    public decimal PayAmount { get; set; }

    /// <summary>
    /// 開戶行
    /// </summary>
    public string OpeningBank { get; set; }

    /// <summary>
    /// 收款單元
    /// </summary>
    public string CollectionMonad { get; set; }

    /// <summary>
    /// 銀行帳號
    /// </summary>
    public string BankAccount { get; set; }

    /// <summary>
    /// 經辦人
    /// </summary>
    public string ResponseiblePerson { get; set; }

    /// <summary>
    /// 分擔引導
    /// </summary>
    [LevelAttribute(Level = 1)]
    public string Leader { get; set; }

    /// <summary>
    /// 財政審核
    /// </summary>
     [LevelAttribute(Level = 2)]
    public string FinanceApproval { get; set; }

    /// <summary>
    /// 財政司理審核
    /// </summary>
     [LevelAttribute(Level = 3)]
    public string FinanceManagerApproval { get; set; }

    /// <summary>
    /// 財政總監審核
    /// </summary>
     [LevelAttribute(Level = 4)]
    public string FinanceDirectorApproval { get; set; }

    /// <summary>
    /// CEO審核
    /// </summary>
     [LevelAttribute(Level = 5)]
    public string CEOApproval { get; set; }

    /// <summary>
    /// 流水號
    /// </summary>
    public string SerialNumber { get; set; }
  }

  public class LevelAttribute : Attribute
  {
    public int Level { get; set; }
  }
var toBePaidComment = persistant.GetTobePaidRecepitComment(ArrayList.Adapter(toBePaidModel.Select(u => u.SerialNumber).ToList()));
  var specialPropertyInfo = (from property in typeof(CuriseShipSpecialPrintModel).GetProperties()
                    where property.GetCustomAttributes(typeof(LevelAttribute), false).Count() > 0
                    select property).ToList();

 toBePaidModel.ForEach((item)=>{
    ShipSpecialPrintModel temp = new ShipSpecialPrintModel()
     {
         SupplierUnderTaker = supplierUnderTaker;
         CustomerSerialNumber = item.CustomerOrderNumber;
         PayAmount = item.PayAmount;
         OpeningBank = item.PayBank;
         CollectionMonad = item.Payee;
         ResponseiblePerson = item.Creator;
         SerialNumber = item.SerialNumber;
     };
    var thisComments=toBePaidComment.Where(u=>u.SerialNumber =item.SerialNumber ).ToList();
    thisComment.ForEach((cm)=>
    {
     if(cm.ApprovalLevel==(specialPropertyInfo.GetCustomAttributes(typeof(LevelAttribute),false).First() as LevelAttribute).Level)
     {
       cm.SetValue(model,cm.Creator,null);
     } 
    });
 })

    但是看到,propertyInfos那裡根本上每輪回一次都須要去反射查找下元素,為了不如許的機能消費,決議再修正一翻,界說一個字典去存儲SpecialPrintModel標有特征類的字段。

   著手操作第三版本

Dictionary<int, PropertyInfo> dic = new Dictionary<int, PropertyInfo>();
  propertyInfos.ForEach((myProperty) => {      dic.Add((a.GetCustomAttributes(typeof(LevelAttribute),false).First() as LevelAttribute).Level,myProperty));
   } );

 comments.ForEach((cm) =>
          {
              if (dic.Keys.Contains(cm.ApprovalLevel))
              {
                dic[cm.ApprovalLevel].SetValue(model, cm.Creator, null);
              }
          });

   整體經由三次的修正,曾經防止if...else的代碼。如許而言,也比擬合適前面好比再須要打印CTO審核的稱號。那樣只須要再Model類外面填寫字段與在字段上加上個殊效。

  總結

      就像我同事說的那樣,做義務工作只需想一想、多敲幾回。一些成績就不是成績了。好了,明天就寫到這裡吧。晚安列位!

請您花一點時光將文章分享給您的同伙或許留下評論。我們將會由衷感激您的支撐!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved