反射学习系列3-反射实例应用
反射学习系列目录
反射学习系列1-反射入门
反射学习系列2-特性(Attribute)
反射学习系列3-反射实例应用
作者
例子这个东西其实挺难弄得,弄个简单的,虽然能说明问题但却容易让人觉得没实用价值,弄个有实用价值却又往往牵扯很多别的技术甚至牵扯很多业务逻辑,看起来很复杂很难懂。在这里我尽量追求几个有实用价值又不复杂的例子。
1、使用反射通过读取配置文件来动态的创建相关类的对象
我们先来看看Main函数和需要动态加载的对象在同一个程序集的情况
结构图:
接口
interface ILog
{
bool Write(string message);
bool Write(Exception ex);
}
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;
}
}
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;
}
}
<?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)名即可。
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-反射入门 反射学习系列2-特性(Attribute) 反射学习系列3-反射实例应用 作者 Reflection,中文翻译为反射.这是.Net中获取运行时类型信息的方式 ...
- 反射学习系列2-特性(Attribute)
先看一个简单的例子 [Table(Name="dbo.[User]")] public partial class User { 当C#编译器发现这个属性有一个特性Table时,首 ...
- 反射学习4-通过反射机制动态创建和访问数组
一.前言 java.lang.reflect.Array类提供了动态创建和访问数组元素的各种静态方法. static Object newInstance(Class<?> comp ...
- 学习Kotlin(七)反射和注解
推荐阅读: 学习Kotlin(一)为什么使用Kotlin 学习Kotlin(二)基本语法 学习Kotlin(三)类和接口 学习Kotlin(四)对象与泛型 学习Kotlin(五)函数与Lambda表达 ...
- Java基础与提高干货系列——Java反射机制
前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制 ...
- java技术详解_Java反射技术详解及实例解析
前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替 ...
- java反射 pdf_java反射学习笔记整理.pdf
java反射学习笔记整理.pdf 还剩 15页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: Java 反射笔记 ...
- android 集成同一interface不同泛型_C# 基础知识系列- 10 反射和泛型(二)
0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...
- java反射机制深入详解_Java基础与提高干货系列——Java反射机制
前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制 ...
最新文章
- linux如何修改主机名
- 虚拟机屏幕界面自适应调整
- [RabbitMQ]消息应答概念_消息手动应答代码
- 经典10046剖析案例-2
- loadrunner使用system()函数调用Tesseract-OCR识别验证码遇到的问题
- 月薪3万Java优秀简历模板
- linux 生成p12证书,Linux下使用openssl制作CA及证书颁发
- 激活visio(2019)
- 如何免费将jpg转换为word可编辑
- 零基础如何搭建个人网站,附完整建站步骤!
- java关联vss 80020009,80020009: Invalid password[src=SourceSafe,guid=null]
- 在服务端录制语音视频
- 计算机系云,计算机与信息技术学院
- python 和vba在财务上_Excel,VBA太烦!PowerBI太贵!可以用Python处理公司财务数据并实现可视化吗?...
- c语言中shift f12组合建,C++学习1-(C语言基础、VS快捷键)
- 超神,chatexcel快速制作任意excel表格,给出指令即可
- [Intensive Reading]图像生成:SaGAN
- vue 中provide的用法_vue中provide和inject的用法
- AI原创生成器1.3版-9大改动
- 软考A计划-软件设计师(高级程序员)考试大纲
热门文章
- android中AsyncTask和Handler对比
- GrideView属性的学习
- linux执行windows创建的脚本,如何在Windows 10上创建和运行Bash Shell脚本 | MOS86
- html php获取post数据格式,html - php文件无法得到POST过来的数据
- JAVA生产环境验证_Java生产环境下性能监控与调优详解
- GC的作用域,方法区和堆
- 电脑卡顿,最先升级这个硬件,运行速度可快速提升!
- 盘点 20多种基本Java库和API,值得收藏!
- mysql 时间chuo格式化_Mysql时间戳与时间格式转换问题汇总
- elasticsearch 删除满足条件的语句_ELK从入门到还未精通(二)——ElasticSearch上篇