程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 反射的妙用_項目中的時間配置問題

反射的妙用_項目中的時間配置問題

編輯:C#入門知識

內容摘要

1:闡述問題

2:分析問題,解決問題

3:演示解決方案

1:闡述問題

      有時候,我們會遇上這樣一個問題:有很多條件 condition1 、condition2 、condition3、condition4 、condition5......這些條件各不相同,可能同時配置其中幾個,這幾個條件有一個交集,交集內部就是我們需要的。

  給一個實例吧。用戶在系統中配置了一個時間條件集合,用戶可以按照年、月、周或者日來配置,按照其中一種來配置,下面有很多條件可以選擇,其中開始日期和時間是必須配置的,最後會形成一個xml信息存儲在數據庫裡面,我們會用當前時間判斷每個用戶的配置條件,如何符合,我們把他的郵箱拿出放到一個字符串尾部,不符合則不管,最後這個字符串就是所有符合用戶配置條件的郵箱集合,我們可以把我們的信息推送給這些用戶。其中xml按照月配置的如下:

View Code

StartDateTime是開始時間,它是一個基本條件,每個配置信息裡面都必須存在。MonthlyDOWRecurrence是代表是按照月來配置的(也可能是WeeklyRecurrence周、DailyRecurrence日等)這個xml節點下面存在很多條件,例如WhichWeek是代表哪一周,DaysOfWeek表示每周的哪一天,又或者MonthsOfYear是每年的哪幾個月。

     問題就是這樣,我從數據庫MatchData得到所有用戶的配置的數據集 Id、Email、MatchData(sql :SELECT [Id],[Email],[MatchData]FROM [MatchData].[dbo].[EmailInTime]),MatchData就是我們的配置xml信息,從集合中找出所有符合條件的用戶Email。

2:分析問題,解決問題

     如果你遇上了啦,該如何處理呢?下面是我的處理方法,如果你有更好的辦法,請給我留意,不吝賜教,謝謝!

     有人可以會總結一下有多少個條件,例如10個condition,然後寫成是個if語句從上到下去判斷是否存在這個條件,如果存在,判斷是否當前時間符合這個條件。

View Code

這是一個偽代碼,簡單模擬了一下,大家都會發現很多問題,

1:判斷是否存在這個條件在xml裡面,耗性能;

2:有很多條件是不用去判斷的,最好是xml配置文件裡面有什麼條件,我們就去判斷什麼條件;

3:擴展性差,當我們需要條件更多的條件的時候,需要修改已有的代碼。

如何解決這三個問題呢?遍歷xml,我們就可以解決第1個問題;遇上什麼條件我們判斷什麼條件,這個可以解決第2個問題;利用每個條件都封裝成方法,遇到條件的時候反射到對應的方法,就解決了第3個問題。

3:演示解決方案

      下面我把解決方案的數據庫和代碼展現給大家,希望能看到你的寶貴意見!

數據庫結構如下:

數據庫在代碼的App_Data文件夾下,下載代碼可以得到。

定義好數據庫後,我們看一下解決方案:

      工程下面包含三個類SqlHelper、AnalyseMatchData和MatchWithMatchData:SqlHelper類是網上下載的幫助工具類,用於操作數據庫;AnalyseMatchData類只包含一個公共的方法GetMailAddressByMatchData,作為對外提供的API接口;MatchWithMatchData類是程序集內部類internal class ,因為我們一個會分層,把這下代碼放在一個類庫裡面,這裡面包含的是每個條件反射的方法。然後就是一個web.config配置文件和一個Index頁面,Index頁面用於測試效果,web.config配置文件裡面當然就是連接字符串了啦,如果要用本人的代碼就需要附加數據庫和修改配置的連接字符串了,相信對大家都是小KS了。

                               MatchWithMatchData matchFunction;
         Type matchType;
   
                       connectionStr = System.Configuration.ConfigurationManager.ConnectionStrings[             matchDataSqlStr =              matchFunction =              matchType =             xmldoc =          }

首先是定義需要的使用的全局變量,然後再構造函數裡面初始化變量,細心的朋友會看到當前時間nowDt變量沒有初始化,因為應該放在後面的api接口裡面,當前時間應該是用戶調用接口的時間。

          
                   
          
                        StringBuilder emailAddresses =              nowDt = Convert.ToDateTime();              (SqlDataReader dr =                                         matchData = dr.GetString(dr.GetOrdinal(                                                emails = dr.GetString(dr.GetOrdinal(                         emailAddresses.Append(.IsNullOrWhiteSpace(emails) ? .Empty :  +                 emailAddresses.Length >  ? emailAddresses.Remove(, ).ToString() :            
                   
          
          
          
           IsMatchWithMatchData(               result =               
                  XmlNodeList xmllist = xmldoc.SelectSingleNode(                 DateTime startDt = Convert.ToDateTime(xmllist[                   (XmlNode xmlnode                       MethodInfo method = matchType.GetMethod(xmlnode.Name + , BindingFlags.Instance |                      oj = method.Invoke(matchFunction,                                                result = result &&                     
                                                         
                             }
GetMailAddressByMatchData方法是對應的 api接口他需要遍歷從數據庫裡面得到的數據集,最後把符合條件的email地址返回給調用方。其中比較關鍵的是IsMatchWithMatchData方法用於判斷xml配置條件和當前的時間nowDt的比較,如何前期時間在配置的時間條件內返回為真true否則為假false。遍歷xml節點,反射到對應的方法,方法的名稱是很有講究的,是節點名稱後面加一個後綴xmlnode.Name + "Function"。
這樣我們達到了業務的分離,每一個方法表示一個條件業務,需要擴展的時候,新增一種xml節點類型,然後新添加一個方法,其他的一概不用管,是不是很方便!
有人說反射消耗性能,何不使用switch想簡單工廠一樣,遇到什麼節點調用什麼方法。其實我不太提倡這種方式:
1:擴張性沒有反射好,擴展的時候需要修改代碼,不符合開閉原則;
2:xml現在是兩層條件,如果用switch,需要嵌套地使用switch了,如果以後變成三層的呢?所有靈活度也不如反射。
3:其實現在反射的性能愈來愈好啦,幾乎和一般的方式調用很接近了。我曾使用一萬六千多條在3秒內完成,相信我們的員工沒有這麼多吧!也可以做一些其他的優化,例如利用緩沖,還有及時條件中只要一個條件為false,就直接返回為假,不用檢測所有的XML裡面的條件,相信你有更多的方式優化它。
反射的方法類MatchWithMatchData裡面:
View Code

 

   比較有意思的是WhichWeekFunction方法,判斷當前日期是哪一周,MonthlyDOWRecurrenceFunction等方法下面,還有條件,又使用了反射的方式調用。整體是如此簡單,如此容易理解。測試的時候,把DateTime.Now;//Convert.ToDateTime("2013-06-26T22:15:00.000+08:00");//改成Convert.ToDateTime("2013-06-26T22:15:00.000+08:00");//DateTime.Now;//,這是一個小技巧。這個Convert.ToDateTime("2013-06-26T22:15:00.000+08:00");測試用例下面有數據,總體跟蹤一遍,就能理解這個代碼
   最後祝大家好運,希望在能夠幫助大家,也希望大家能多提意見,覺得有收獲的幫助頂一下。
代碼下載:http://files.cnblogs.com/zhangxl/MatchData.zip
文章出處:http://www.cnblogs.com/zhangxl/p/reflection.html 











		
		

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