程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> 反射學習系列3-反射實例應用

反射學習系列3-反射實例應用

編輯:關於C#

例子這個東西其實挺難弄得,弄個簡單的,雖然能說明問題但卻容易讓人覺得沒實用價值,弄個有實用價值卻又往往牽扯很多別的技術甚至牽扯很多業務邏輯,看起來很復雜很難懂。在這裡我盡量追求幾個有實用價值又不復雜的例子。

1、使用反射通過讀取配置文件來動態的創建相關類的對象

我們先來看看Main函數和需要動態加載的對象在同一個程序集的情況

結構圖:

接口

interface ILog
  {
    bool Write(string message);
    bool Write(Exception ex);
  }

TextFileLog

class 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;
    }
  }

XmlFileLog

class 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、插件編程技術

插件是指遵循一定的接口規范、可以動態加載和運行的程序模塊。從上面的例子可以看出,通過反射可以非常方便的動態加載程序集。因此,利用反射的動態加載代碼能力,可以很容易的實現插件。插件編程的要點是使用接口來定義插件的功能特征。插件的宿主程序通過接口來確認、裝載和執行插件的功能,實現插件功能的所有類都必須實現定義插件的接口。

這裡只是選貼一部分代碼,詳細分析請看源碼

結構圖

接口部分

publicinterfaceIHost
  {
    List<ILog>Plugins{get;}
    intLoadPlugins(stringpath);
    ILogGetLog(stringname);
  }
publicinterfaceILog
  {
    boolWrite(stringmessage);
    boolWrite(Exceptionex);
  }

宿主實現

publicclassHost:IHost
  {
    privateList<ILog>plugins=newList<ILog>();
    #regionIHost成員
    publicList<ILog>Plugins
    {
      get{returnplugins;}
    }
    publicintLoadPlugins(stringpath)
    {
      string[]assemblyFiles=Directory.GetFiles(path,"*.dll");
      foreach(varfileinassemblyFiles)
      {
        Assemblyassembly=Assembly.LoadFrom(file);
        foreach(vartypeinassembly.GetExportedTypes())
        {
          if(type.IsClass&&typeof(ILog).IsAssignableFrom(type))
          {
            ILogplugin=Activator.CreateInstance(type)asILog;
            plugins.Add(plugin);
          }
        }
      }
      returnplugins.Count;
    }
    publicILogGetLog(stringname)
    {
      foreach(variteminplugins)
      {
        if(item.GetType().ToString()==name)
        {
          returnitem;
        }

      }
      returnnull;
    }
    #endregion
  }

ILog的實現和上例基本一樣,請參考

主程序代碼

staticvoidMain(string[]args)
    {
      Host.Hosthost=newHost.Host();
      host.LoadPlugins(".");
      InterfaceLayer.ILoglog=host.GetLog(ConfigurationManager.AppSettings["LogType"].ToString());
      log.Write(newException("異常測試"));
    }

3、分析對象,得到對象中的屬性值

大家使用應都用過asp.net中的DropdownList,在綁定其值的時候絕大多數情況下我們做的都是同樣的事情,獲得數據源,根據數據源中的某些列綁定控件,下邊我們來說說通用情況的處理方式。我們只需要提供數據集合,以及需要綁定到控件的兩個屬性(text,value)名即可。

publicclassDDlControl
  {
    privateListControlunderlyingList;
    publicDDlControl(ListControlunderlyingList)
    {
      this.underlyingList=underlyingList;
    }
    publicvoidAdd(IDDLddl)
    {
      underlyingList.Items.Add(newListItem(ddl.Name,ddl.Value));
    }
    publicvoidAdd<T>(Tt,stringnameStr,stringvalueStr)
    {
      stringname=Convert.ToString(t.GetType().InvokeMember
         (nameStr,System.Reflection.BindingFlags.GetProperty,null,t,null));
      stringvalue=Convert.ToString(t.GetType().InvokeMember
        (valueStr,System.Reflection.BindingFlags.GetProperty,null,t,null));
      Add(newDDLStruct(name,value));

    }
    publicvoidClear()
    {
      underlyingList.Items.Clear();
    }
    publicIDDLSelectedItem
    {
      get
      {
        ListItemitem=underlyingList.SelectedItem;
        returnnewDDLStruct(item.Text,item.Value);
      }
    }
    publicvoidBindTo<T>(IEnumerable<T>list,stringnameStr,stringvalueStr)
    {
      Clear();
      foreach(variteminlist)
      {
        Add<T>(item,nameStr,valueStr);
      }
    }
    publicstringSelectValue
    {
      get
      {
        returnunderlyingList.SelectedValue;
      }
      set
      {
        underlyingList.SelectedValue=value;
      }
    }
  }
publicstructDDLStruct
  {
    publicDDLStruct(stringname,stringvalue)
    {
      this.name=name;
      this.value=value;
    }
    privatestringname;
    privatestringvalue;
    publicstringName
    {
      get{returnname;}
    }
    publicstringValue
    {
      get{returnvalue;}
    }
  }

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