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

反射学习系列目录

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

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

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

作者

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

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

结构图:


接口

 

ContractedBlock.gifExpandedBlockStart.gif接口
interface ILog
    {
        
bool Write(string message);
        
bool Write(Exception ex);
    }

 

 

ContractedBlock.gifExpandedBlockStart.gifTextFileLog
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;
        }
    }

 

 

ContractedBlock.gifExpandedBlockStart.gifXmlFileLog
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;

        }
    }

 

 

ContractedBlock.gifExpandedBlockStart.gifApp.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>

 

 

ContractedBlock.gifExpandedBlockStart.gif主程序
 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
        }

 

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

 

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

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

结构图

 

接口部分

 

ContractedBlock.gifExpandedBlockStart.gif接口
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);

    }

 

宿主实现

 

ContractedBlock.gifExpandedBlockStart.gif宿主实现
 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的实现和上例基本一样,请参考

主程序代码

 

ContractedBlock.gifExpandedBlockStart.gif主程序代码
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)名即可。

 

ContractedBlock.gifExpandedBlockStart.gifCode
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; }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/299599.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么向女朋友解释什么叫区块链?

全世界只有3.14 % 的人关注了青少年数学之旅现在最火热的科技和风口&#xff0c;无疑就是“区块链”了。很多投行面试中也总是会被问到 于是&#xff0c;发生了下面的故事……有一对恩爱的男女朋友开始了这样的对话&#xff0c;我们暂且叫他们小明和小花吧。&#xff08;将就点…

遭遇价格欺诈

周末和朋友逛街时&#xff0c;买了副皮手套&#xff0c;店家说帮朋友代卖的&#xff0c;标价318元&#xff0c;打五折&#xff0c;又跟店家讲了下价&#xff0c;虽然店家表现的老大不情愿&#xff0c;但最终还是以130买进。 回家后顺手从网上查了下&#xff0c;淘宝网上才卖75&…

超详细图解!【MySQL进阶篇】MySQL索引原理

索引类型 索引可以提升查询速度&#xff0c;会影响where查询&#xff0c;以及order by排序。MySQL索引类型如下&#xff1a; 从索引存储结构划分&#xff1a;B Tree索引、Hash索引、FULLTEXT全文索引、R Tree索引 从应用层次划分&#xff1a;普通索引、唯一索引、主键索引、复…

ExtJs学习笔记(21)-使用XTemplate结合WCF显示数据

个人认为&#xff0c;XTemplate是ExtJs中最灵活的用来显示数据的组件&#xff0c;有点类似aspx中的Repeater控件&#xff0c;显示数据的模板完全可以由用户以html方式来定制. 先给一个官方的静态示例(稍微改了下)&#xff0c;代码并不复杂&#xff0c;关键的地方&#xff0c;我…

Blazor 路由及导航开发指南

翻译自 Waqas Anwar 2021年4月2日的文章 《A Developer’s Guide To Blazor Routing and Navigation》 [1]检查传入的请求 URL 并将它们导航到对应的视图或页面是每个单页应用程序 (SPA) 框架的基本功能。Blazor Server 和 WebAssembly 应用程序也同样支持使用一些内置组件和服…

超详细图解!【MySQL进阶篇】SQL优化-索引-存储引擎

1. Mysql的体系结构概览 整个MySQL Server由以下组成 Connection Pool : 连接池组件Management Services & Utilities : 管理服务和工具组件SQL Interface : SQL接口组件Parser : 查询分析器组件Optimizer : 优化器组件Caches & Buffers : 缓冲池组件Pluggable Storag…

数据之美

数据是抽象的&#xff0c;尤其是海量数据&#xff0c;人的大脑很难直接对大量数据进行分析并获得印象&#xff0c;然而从另一个角度看&#xff0c;数据也可以异常美丽&#xff0c;人们设计了很多工具&#xff0c;让枯燥的数据图形化&#xff0c;本文介绍了50个数据图形化工具&a…

一个孩子能长大成人到底有多不容易? | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅(图源警民直通车-上海&#xff0c;侵权删&#xff09;

差距50倍!为什么Web API第一次执行这么慢?

前言新建一个ASP.NET Core Web API项目&#xff0c;使用命令行方式启动&#xff0c;连续发送多次请求。从下图的时间线可以发现&#xff0c;第一次执行&#xff08;116ms&#xff09;比后面的&#xff08;2ms&#xff09;慢了很多:在这100多ms中&#xff0c;Web API到底做了些什…

Exchange服务器系列课程之四--管理Exchange收件人

前面已经讨论了Exchange的安装&#xff0c;今天我们来讨论一下Exchange服务器的用户管理。管理Exchange的工具在第二篇文章已经讨论过了&#xff0c;这里不再阐述。Exchange中的收件人对象有三种&#xff1a;用户&#xff0c;组&#xff0c;联系人。我们可以为收件人对象启用邮…

动力强劲的星型发动机,为何不用在汽车上呢?

全世界只有3.14 % 的人关注了青少年数学之旅星型发动机嘚瑟的模样&#xff0c;一定让人过目不忘——对&#xff0c;虽然它看起来妖娆&#xff0c;但动力却十分强劲。那它为什么没在汽车上普及呢&#xff1f;我们一起来看看&#xff01;什么是星型发动机星型发动机&#xff0c;顾…

超详细图解!【MySQL进阶篇】存储过程,视图,索引,函数,触发器

超详细图解&#xff01;【MySQL进阶篇】存储过程,视图,索引,函数,触发器1.1 下载Linux 安装包1.2 安装MySQL1.3 启动 MySQL 服务1.4 登录MySQL2\. 索引2.1 索引概述2.2 索引优势劣势2.3 索引结构2.3.1 BTREE 结构2.3.3 BTREE 结构2.3.3 MySQL中的BTree2.4 索引分类2.5 索引语法…

.Net Core with 微服务 - 分布式事务 - 2PC、3PC

最近比较忙&#xff0c;好久没更新了。这次我们来聊一聊分布式事务。在微服务体系下&#xff0c;我们的应用被分割成多个服务&#xff0c;每个服务都配置一个数据库。如果我们的服务划分的不够完美&#xff0c;那么为了完成业务会出现非常多的跨库事务。即使按照 DDD 的原则来切…

2019优质公众号大盘点,果断收藏了慢慢看吧 ~

全世界只有3.14 % 的人关注了青少年数学之旅又到年底了啦&#xff0c;也到了一年一度的年底盘点时间。那么2019年&#xff0c;又有哪些优质公众号崭露头角呢&#xff1f;本期将为您盘点几个优质公众号&#xff0c;总有一个刷屏过你的朋友圈&#xff01;长按二维码&#xff0c;选…

让未备案的网站先飙起来

让未备案的网站先飙起来作者&#xff1a;田逸&#xff08;sery163.com&#xff09;国人在技术方面的创新能力不怎么样&#xff0c;但是在设置障碍&#xff0c;折腾自己人的方面的创造性却登峰造极&#xff0c;比如网站备案。要备案也没什么问题&#xff0c;毕竟大家都是老老实实…

TDengine和DolphinDB哪个更好,哈哈哈哈,闲来无聊分析了一下。

#拥抱开源—涛思数据TDengine有奖征稿# TDengine是专为时序数据设计的&#xff0c;针对的是物联网、工业互联网、IT运维场景。这些场景是不需要特殊的查询函数的&#xff0c;更关心的是写入速度、查询速度。而且这些场景下&#xff0c;也需要一些其他数据库不具备的功能&#…

记一次 .NET 某WMS仓储打单系统 内存暴涨分析

一&#xff1a;背景 1. 讲故事七月中旬有一位朋友加wx求助&#xff0c;他的程序在生产上跑着跑着内存就飙起来了&#xff0c;貌似没有回头的趋势&#xff0c;询问如何解决&#xff0c;截图如下&#xff1a;和这位朋友聊下来&#xff0c;感觉像是自己在小县城当了个小老板&#…

一分钟读懂一个数学时代,看完不跪算我输!

▲ 点击查看上帝说&#xff0c;要有光&#xff0c;于是便有了光。而香农说&#xff0c;要有熵&#xff0c;于是信息化时代正式拉开帷幕。克劳德艾尔伍德香农&#xff08;Claude Elwood Shannon&#xff09;被尊称为“信息论之父”。不管你是否知道他&#xff0c;是如何看待他…

秋招面试我去了拼多多,直接被问JVMGC底层原理和算法,我吊打面试官

JVM 常用参数设置积累 # 堆的初始值&#xff0c;默认物理内存的1/64 -Xms: # 堆的最大值&#xff0c;默认物理内存的1/4 -Xmx: # 年轻代大小「在整个堆内存大小确定的情况下&#xff0c;增大年轻代将会减小年老代&#xff0c;反之亦然。此值关系到JVM垃圾回收&#xff0c;对系…

php中使用exec,system等函数调用系统命令

2019独角兽企业重金招聘Python工程师标准>>> 注意:要想使用这二个函数php.ini中的安全模式必须关闭&#xff0c;要不然为了安全起见php是不让调用系统命令的。  先看一下php手册对这二个函数的解释:  exec --- 执行外部程式  语法 : string exec ( string com…