反射学习系列目录

反射学习系列1-反射入门

反射学习系列2-特性(Attribute)

反射学习系列3-反射实例应用

作者

例子这个东西其实挺难弄得,弄个简单的,虽然能说明问题但却容易让人觉得没实用价值,弄个有实用价值却又往往牵扯很多别的技术甚至牵扯很多业务逻辑,看起来很复杂很难懂。在这里我尽量追求几个有实用价值又不复杂的例子。
1、使用反射通过读取配置文件来动态的创建相关类的对象

我们先来看看Main函数和需要动态加载的对象在同一个程序集的情况

结构图:


反射学习系列3-反射实例应用

接口

 

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

 

 

 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 : 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;

        }
    }

 

 


  <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>

 

 

 Main()
        {
            #region 同程序集下
            System.Type type 
= System.Type.GetType(ConfigurationManager.AppSettings["LogType"].ToString());
            ILog log 
= (ILog)Activator.CreateInstance(type);
            log.Write(
new Exception("异常测试"));
            
#endregion
        }

 

如果在不同的程序集下,那主函数和配置会略有不同

 

 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、插件编程技术
插件是指遵循一定的接口规范、可以动态加载和运行的程序模块。从上面的例子可以看出,通过反射可以非常方便的动态加载程序集。因此,利用反射的动态加载代码能力,可以很容易的实现插件。插件编程的要点是使用接口来定义插件的功能特征。插件的宿主程序通过接口来确认、装载和执行插件的功能,实现插件功能的所有类都必须实现定义插件的接口。

这里只是选贴一部分代码,详细分析请看源码

结构图

 

反射学习系列3-反射实例应用

接口部分

 

 IHost
    {
        List<ILog> Plugins { get; }
        
int LoadPlugins(string path);
        ILog GetLog(
string name);

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

    }

 

宿主实现

 

 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的实现和上例基本一样,请参考

主程序代码

 

[] 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)名即可。

 

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

相关文章: