反射学习系列3-反射实例应用
反射學習系列目錄
反射學習系列1-反射入門
反射學習系列2-特性(Attribute)
反射學習系列3-反射實例應用
作者
例子這個東西其實挺難弄得,弄個簡單的,雖然能說明問題但卻容易讓人覺得沒實用價值,弄個有實用價值卻又往往牽扯很多別的技術甚至牽扯很多業務邏輯,看起來很復雜很難懂。在這里我盡量追求幾個有實用價值又不復雜的例子。
1、使用反射通過讀取配置文件來動態的創建相關類的對象
我們先來看看Main函數和需要動態加載的對象在同一個程序集的情況
結構圖:
接口
?
接口interface?ILog
????{
????????bool?Write(string?message);
????????bool?Write(Exception?ex);
????}
?
?
TextFileLogclass?TextFileLog?:?ILog
????{
????????public?bool?Write(string?message)
????????{
????????????string?fileDir?=?ConfigurationManager.AppSettings["LogTarget"].ToString();
????????????using?(StreamWriter?w?=?File.AppendText(fileDir))
????????????{
????????????????//?w.Write("?Log?Entry?:?");
????????????????w.WriteLine("發生時間{0}",?DateTime.Now.ToLocalTime().ToString());
????????????????w.WriteLine("日志內容為:{0}",?message);
????????????????w.WriteLine("-------------------------------");
????????????????//?Update?the?underlying?file.
????????????????w.Flush();
????????????????w.Close();
????????????}
????????????return?true;
????????}
????????public?bool?Write(Exception?ex)
????????{
????????????Write(ex.Message);
????????????return?true;
????????}
????}
?
?
XmlFileLogclass?XmlFileLog?:?ILog
????{
????????public?bool?Write(string?message)
????????{
????????????string?xmlFilePath?=?ConfigurationManager.AppSettings["LogTarget"].ToString();
????????????if?(File.Exists(xmlFilePath))
????????????{
????????????????XmlDocument?doc?=?new?XmlDocument();
????????????????doc.Load(xmlFilePath);
????????????????XmlDocumentFragment?docFrag?=?doc.CreateDocumentFragment();
????????????????XmlNode?nod?=?doc.SelectSingleNode("Logs");
????????????????docFrag.InnerXml?=?"<Log><Time>"?+?DateTime.Now.ToLocalTime().ToString()
????????????????????+?"</Time><Message>"?+?message?+?"</Message></Log>";
????????????????nod.AppendChild(docFrag);
????????????????doc.Save(xmlFilePath);
????????????????return?true;
????????????}
????????????else
????????????{
????????????????XmlWriterSettings?settings?=?new?XmlWriterSettings();
????????????????settings.Indent?=?true;?????//設置縮進???????
????????????????settings.ConformanceLevel?=?ConformanceLevel.Auto;
????????????????settings.IndentChars?=?"?";
????????????????settings.OmitXmlDeclaration?=?false;
????????????????using?(XmlWriter?writer?=?XmlWriter.Create(xmlFilePath,?settings))
????????????????{
????????????????????//Start?writing?the?XML?document
????????????????????writer.WriteStartDocument(false);
????????????????????//Start?with?the?root?element
????????????????????writer.WriteStartElement("Logs");
????????????????????writer.WriteStartElement("Log");
????????????????????writer.WriteStartElement("Time");
????????????????????writer.WriteString(DateTime.Now.ToLocalTime().ToString());
????????????????????writer.WriteEndElement();
????????????????????writer.WriteStartElement("Message");
????????????????????writer.WriteString(message);
????????????????????writer.WriteEndElement();
????????????????????writer.WriteEndElement();
????????????????????writer.WriteEndDocument();
????????????????????//Flush?the?object?and?write?the?XML?data?to?the?file
????????????????????writer.Flush();
????????????????????return?true;
????????????????}
????????????}
????????}
????????public?bool?Write(Exception?ex)
????????{
????????????Write(ex.Message);
????????????return?true;
????????}
????}
?
?
App.config配置<?xml?version="1.0"?encoding="utf-8"??>
<configuration>
??<appSettings>
????<add?key="LogType"?value="LogClassLibrary.TextFileLog"/>
????<!--
????本程序集配置
????<add?key="LogType"?value="ConsoleApplication2.Log例子.TextFileLog"/>
????-->
????<!--?XmlFileLog??TextFileLog-->
????<add?key="LogTarget"?value="c:\log.txt"/>
??</appSettings>
</configuration>
?
?
主程序?public?static?void?Main()
????????{
????????????#region?同程序集下
????????????System.Type?type?=?System.Type.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
????????????ILog?log?=?(ILog)Activator.CreateInstance(type);
????????????log.Write(new?Exception("異常測試"));
????????????#endregion
????????}
?
如果在不同的程序集下,那主函數和配置會略有不同
?
不同程序集主函數?public?static?void?Main()
????????{
????????????#region?不同程序集
????????????string?assemblyPath?=?Path.Combine(Environment.CurrentDirectory,?"LogClassLibrary.dll");
????????????Assembly?a?=?Assembly.LoadFrom(assemblyPath);
????????????Type?type?=?a.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
????????????LogClassLibrary.ILog?log?=?(LogClassLibrary.ILog)type.InvokeMember(null,BindingFlags.CreateInstance,null,null,null);
????????????log.Write(new?Exception("異常測試"));
????????????#endregion
????????}
?
這部分源碼下載
源碼下載
2、插件編程技術
插件是指遵循一定的接口規范、可以動態加載和運行的程序模塊。從上面的例子可以看出,通過反射可以非常方便的動態加載程序集。因此,利用反射的動態加載代碼能力,可以很容易的實現插件。插件編程的要點是使用接口來定義插件的功能特征。插件的宿主程序通過接口來確認、裝載和執行插件的功能,實現插件功能的所有類都必須實現定義插件的接口。
這里只是選貼一部分代碼,詳細分析請看源碼
結構圖
?
接口部分
?
接口public?interface?IHost
????{
????????List<ILog>?Plugins?{?get;?}
????????int?LoadPlugins(string?path);
????????ILog?GetLog(string?name);
????}
?public?interface?ILog
????{
????????bool?Write(string?message);
????????bool?Write(Exception?ex);
????}
?
宿主實現
?
宿主實現?public?class?Host?:?IHost
????{
????????private?List<ILog>?plugins?=?new?List<ILog>();
????????#region?IHost?成員
????????public?List<ILog>?Plugins
????????{
????????????get?{?return?plugins;?}
????????}
????????public?int?LoadPlugins(string?path)
????????{
????????????string[]?assemblyFiles?=?Directory.GetFiles(path,?"*.dll");
????????????foreach?(var?file?in?assemblyFiles)
????????????{
????????????????Assembly?assembly?=?Assembly.LoadFrom(file);
????????????????foreach?(var?type?in?assembly.GetExportedTypes())
????????????????{
????????????????????if?(type.IsClass?&&?typeof(ILog).IsAssignableFrom(type))
????????????????????{
????????????????????????ILog?plugin?=?Activator.CreateInstance(type)?as?ILog;
????????????????????????plugins.Add(plugin);
????????????????????}
????????????????}
????????????}
????????????return?plugins.Count;
????????}
????????public?ILog?GetLog(string?name)
????????{
????????????foreach?(var?item?in?plugins)
????????????{
????????????????if?(item.GetType().ToString()==name)
????????????????{
????????????????????return?item;
????????????????}
????????????????
????????????}
????????????return?null;
????????}
????????#endregion
????}
?
ILog的實現和上例基本一樣,請參考
主程序代碼
?
主程序代碼static?void?Main(string[]?args)
????????{
????????????Host.Host?host?=?new?Host.Host();
????????????host.LoadPlugins(".");
????????????InterfaceLayer.ILog?log?=?host.GetLog(ConfigurationManager.AppSettings["LogType"].ToString());
????????????log.Write(new?Exception("異常測試"));
????????} 插件編程源碼下載
源碼下載
3、分析對象,得到對象中的屬性值
大家使用應都用過asp.net中的DropdownList,在綁定其值的時候絕大多數情況下我們做的都是同樣的事情,獲得數據源,根據數據源中的某些列綁定控件,下邊我們來說說通用情況的處理方式。我們只需要提供數據集合,以及需要綁定到控件的兩個屬性(text,value)名即可。
?
Codepublic?class?DDlControl?
????{
????????private?ListControl?underlyingList;
????????public?DDlControl(ListControl?underlyingList)
????????{
????????????this.underlyingList?=?underlyingList;
????????}
????????public?void?Add(IDDL?ddl)
????????{
????????????underlyingList.Items.Add(new?ListItem(ddl.Name,?ddl.Value));
????????}
????????public?void?Add<T>(T?t,?string?nameStr,?string?valueStr)
????????{
????????????string?name?=?Convert.ToString(t.GetType().InvokeMember
???????????????????(nameStr,?System.Reflection.BindingFlags.GetProperty,?null,?t,?null));
????????????string?value?=?Convert.ToString(t.GetType().InvokeMember
????????????????(valueStr,?System.Reflection.BindingFlags.GetProperty,?null,?t,?null));
????????????Add(new?DDLStruct(name,value));
????????????
????????}
????????public?void?Clear()
????????{
????????????underlyingList.Items.Clear();
????????}
????????public?IDDL?SelectedItem
????????{
????????????get
????????????{
????????????????ListItem?item?=?underlyingList.SelectedItem;
????????????????return?new?DDLStruct(item.Text,?item.Value);
????????????}
????????}
????????public?void?BindTo<T>(IEnumerable<T>?list,?string?nameStr,?string?valueStr)
????????{
????????????Clear();
????????????foreach?(var?item?in?list)
????????????{
????????????????Add<T>(item,?nameStr,?valueStr);
????????????}
????????}
????????public?string?SelectValue
????????{
????????????get
????????????{
????????????????return?underlyingList.SelectedValue;
????????????}
????????????set
????????????{
????????????????underlyingList.SelectedValue=value;
????????????}
????????}
????}
public?struct?DDLStruct?
????{
????????public?DDLStruct(string?name,?string?value)
????????{
????????????this.name?=?name;
????????????this.value?=?value;
????????}
????????private?string?name;
????????private?string?value;
????????public?string?Name
????????{
????????????get?{?return?name;?}
????????}
????????public?string?Value
????????{
????????????get?{?return?value;?}
????????}
????}
總結
以上是生活随笔為你收集整理的反射学习系列3-反射实例应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html左中右自适应布局,CSS左中右自
- 下一篇: ssm 酒店管理系统