反射学习系列目录

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

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

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

作者

例子这个东西其实挺难弄得,弄个简单的,虽然能说明问题但却容易让人觉得没实用价值,弄个有实用价值却又往往牵扯很多别的技术甚至牵扯很多业务逻辑,看起来很复杂很难懂。在这里我尽量追求几个有实用价值又不复杂的例子。
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、插件编程技术
插件是指遵循一定的接口规范、可以动态加载和运行的程序模块。从上面的例子可以看出,通过反射可以非常方便的动态加载程序集。因此,利用反射的动态加载代码能力,可以很容易的实现插件。插件编程的要点是使用接口来定义插件的功能特征。插件的宿主程序通过接口来确认、装载和执行插件的功能,实现插件功能的所有类都必须实现定义插件的接口。

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

结构图

接口部分

接口
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)名即可。

Code
public 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-反射实例应用相关推荐

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

    反射学习系列目录 反射学习系列1-反射入门 反射学习系列2-特性(Attribute) 反射学习系列3-反射实例应用 作者 Reflection,中文翻译为反射.这是.Net中获取运行时类型信息的方式 ...

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

    先看一个简单的例子 [Table(Name="dbo.[User]")] public partial class User { 当C#编译器发现这个属性有一个特性Table时,首 ...

  3. 反射学习4-通过反射机制动态创建和访问数组

    一.前言 java.lang.reflect.Array类提供了动态创建和访问数组元素的各种静态方法. static Object    newInstance(Class<?> comp ...

  4. 学习Kotlin(七)反射和注解

    推荐阅读: 学习Kotlin(一)为什么使用Kotlin 学习Kotlin(二)基本语法 学习Kotlin(三)类和接口 学习Kotlin(四)对象与泛型 学习Kotlin(五)函数与Lambda表达 ...

  5. Java基础与提高干货系列——Java反射机制

    前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制 ...

  6. java技术详解_Java反射技术详解及实例解析

    前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替 ...

  7. java反射 pdf_java反射学习笔记整理.pdf

    java反射学习笔记整理.pdf 还剩 15页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: Java 反射笔记 ...

  8. android 集成同一interface不同泛型_C# 基础知识系列- 10 反射和泛型(二)

    0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...

  9. java反射机制深入详解_Java基础与提高干货系列——Java反射机制

    前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制 ...

最新文章

  1. linux如何修改主机名
  2. 虚拟机屏幕界面自适应调整
  3. [RabbitMQ]消息应答概念_消息手动应答代码
  4. 经典10046剖析案例-2
  5. loadrunner使用system()函数调用Tesseract-OCR识别验证码遇到的问题
  6. 月薪3万Java优秀简历模板
  7. linux 生成p12证书,Linux下使用openssl制作CA及证书颁发
  8. 激活visio(2019)
  9. 如何免费将jpg转换为word可编辑
  10. 零基础如何搭建个人网站,附完整建站步骤!
  11. java关联vss 80020009,80020009: Invalid password[src=SourceSafe,guid=null]
  12. 在服务端录制语音视频
  13. 计算机系云,计算机与信息技术学院
  14. python 和vba在财务上_Excel,VBA太烦!PowerBI太贵!可以用Python处理公司财务数据并实现可视化吗?...
  15. c语言中shift f12组合建,C++学习1-(C语言基础、VS快捷键)
  16. 超神,chatexcel快速制作任意excel表格,给出指令即可
  17. [Intensive Reading]图像生成:SaGAN
  18. vue 中provide的用法_vue中provide和inject的用法
  19. AI原创生成器1.3版-9大改动
  20. 软考A计划-软件设计师(高级程序员)考试大纲

热门文章

  1. android中AsyncTask和Handler对比
  2. GrideView属性的学习
  3. linux执行windows创建的脚本,如何在Windows 10上创建和运行Bash Shell脚本 | MOS86
  4. html php获取post数据格式,html - php文件无法得到POST过来的数据
  5. JAVA生产环境验证_Java生产环境下性能监控与调优详解
  6. GC的作用域,方法区和堆
  7. 电脑卡顿,最先升级这个硬件,运行速度可快速提升!
  8. 盘点 20多种基本Java库和API,值得收藏!
  9. mysql 时间chuo格式化_Mysql时间戳与时间格式转换问题汇总
  10. elasticsearch 删除满足条件的语句_ELK从入门到还未精通(二)——ElasticSearch上篇