这里我又唠叨几句,大家在学习的时候,如看书或者看视频时觉得非常爽,因为感觉基本都看得懂也都挺容易的,其实看懂是一回事,你自己会动手做出来是一回事,自己能够说出来又是另一回事了。应该把学到的东西变成自己的东西,而不是依样画瓢。

在说反射之前,我们先来了解一下什么是程序集?
程序集
程序集是.net中的概念,程序集可以看作是给一堆相关类打一个包,相当于java中的jar包。
程序集包含:
exe与dll的区别。
exe可以运行,dll不能直接运行,因为exe中有一个main函数(入口函数)。
类型元数据这些信息可以通过AssemblyInfo.cs文件来自定义。在每一个.net项目中都存在一个AssemblyInfo.cs文件,代码格式:
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("ReflectedDemo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReflectedDemo")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("7674d229-9929-4ec8-b543-4d05c6500863")]
// 程序集的版本信息由下面四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
这些信息在哪里体现呢?就在我们程序集的属性当中进行体现
我们平时在安装一些CS客户端程序的时候,在安装目录下面会看见许多的程序集文件。
使用程序集的好处
如何添加程序集的引用?
直接添加程序集路径或者添加解决方案中的项目引用。
当我们需要扩展一个程序的时候,你可能会直接在原有的项目中进行添加,那这样的话,如果你的这些代码想共享给别人使用呢?你就可以打包成一个程序集,然后别人只要通过引用你这个程序集就可以进行扩展了。像我们常见的.net第三方框架库,如log4net、unity等等。
注意:不能添加循环引用
什么是添加循环引用?就是说A项目如果添加了B项目的项目引用,那么此时B项目不能再添加A项目的项目引用,也就是说添加项目引用时,必须是单向的,像我们常见的三层框架之间的项目引用。
反射
关于反射,你只要是做.net开发,你就一定天天在用。因为VS的智能提示就是通过应用了反射技术来实现的,还有我们常用的反编译神器Reflector.exe,看它的名字就知道了。项目中比较常见的,是通过结合配置文件来动态实例化对象,如切换数据库实例,或者Sprint.net的通过配置文件来实现依赖注入等。
反射技术其实就是动态获取程序集的元数据的功能,反射通过动态加载dll,然后对其进行解析,从而创建对象,调用成员。
Type是对类的描述,Type类是实现反射的一个重要的类,通过它我们可以获取类中的所有信息,包括方法、属性等。可以动态调用类的属性、方法。
反射的出现让创建对象的方式发生了改变,因为过去面完创建对象都是直接通过new。
dll里面有两部分东西:IL中间语言和metadate元素据。
在.NET中反射用到命名空间是System.Reflection,这里我先通过一个Demo来看反射能做些什么
1、 新建控制台项目ReflectedDemo
2、 新建类库项目My.Sqlserver.Dal
新建两个类SqlServerHelper和SqlCmd,前者为共有类,后者为私有类
namespace My.Sqlserver.Dal
{
public class SqlServerHelper
{
private int age = 16;
public string Name { get; set; }
public string Query()
{
return string.Empty;
}
}
class SqlCmd
{
}
}
3、 项目ReflectedDemo,添加My.Sqlserver.Dal的项目引用,我这样做的目的是为了方便项目ReflectedDemo中的bin目录中时刻存在My.Sqlserver.Dal.dll程序集。
using System;
using System.Reflection;
namespace ReflectedDemo
{
class Program
{
static void Main(string[] args)
{
//加载程序集文件,在bin目录中查找
Assembly assembly = Assembly.Load("My.Sqlserver.Dal");
Console.WriteLine("----------------Modules----------------------");
var modules = assembly.GetModules();
foreach(var module in modules)
{
Console.WriteLine(module.Name);
}
Console.WriteLine("----------------Types----------------------");
var types = assembly.GetTypes(); //获取程序集中所有的类型,包括公开的和不公开的
foreach(var type in types)
{
Console.WriteLine(type.Name);
Console.WriteLine(type.FullName);
var members= type.GetMembers(); //获取Type中所有的公共成员
Console.WriteLine("----------------members----------------------");
foreach(var m in members)
{
Console.WriteLine(m.Name);
}
}
Console.WriteLine("----------------GetExportedTypes----------------------");
var exportedTypes = assembly.GetExportedTypes(); //获取程序集中所有的公共类型
foreach(var t in exportedTypes)
{
Console.WriteLine(t.Name);
}
Console.WriteLine("----------------GetType----------------------");
var typeName= assembly.GetType("SqlServerHelper");//获取程序集中指定名称的类型对象
Console.WriteLine(typeName.Name);
}
}
}
动态创建对象
通过ass.CreateInstance(string typeName) 和Activator.CreateInstance(Type t)方法
他们之间的区别
ass.CreateInstance(string typeName) 会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果没有无参构造函数就会报错。
Assembly assembly = Assembly.Load("My.Sqlserver.Dal");
object obj = assembly.CreateInstance("My.Sqlserver.Dal.SqlServerHelper");
Console.WriteLine(obj.GetType().ToString());
如果我们来修改SqlServerHelper类的代码,添加如下构造函数:
public SqlServerHelper(int age)
{
this.age = age;
}
这个时候再来运行创建实例的代码就会报错了,而编译时是不报错的。
所以我们一般推荐使用Activator.CreateInstance方法来创建反射对象,因为此方法有许多重载,支持将参数传递给构造函数。
此时再调用就不会出现异常了。
Type类中有三个用得比较多的方法:
Type类中还有一个IsAbstract属性:判断是否为抽象的,包含接口。
它们常用的原因是我们通过反射可以取到的东西太多了,我们需要对数据进行过滤。
添加类BaseSql,让类SqlServerHelper继承自BaseSql
然后查看调用代码:
bool result = typeof(BaseSql).IsAssignableFrom(typeof(SqlServerHelper));
Console.WriteLine(result);
SqlServerHelper _SqlServerHelper = new SqlServerHelper(1); bool result = typeof(SqlServerHelper).IsInstanceOfType(_SqlServerHelper); Console.WriteLine(result);
SqlServerHelper _SqlServerHelper = new SqlServerHelper(1);
bool result = typeof(SqlServerHelper).IsSubclassOf(typeof(BaseSql));
Console.WriteLine(result);
项目中常用的利用反射来动态切换数据库Demo:
新建类库项目My.Sql.IDal,并添加接口ISqlHelper。通过接口来实现数据库操作的类的解耦,因为接口是抽象的。
public interface ISqlHelper
{
string Query();
}
添加类库项目My.MySql.Dal,并新增类MySqlHelper.cs
My.Sqlserver.Dal、My.MySql.Dal项目分别添加对项目My.Sql.IDal的引用。让SqlServerHelper继承自接口ISqlHelper
public class MySqlHelper : ISqlHelper
{
public string Query()
{
return this.GetType().ToString();
}
}
public class SqlServerHelper :ISqlHelper
{
private int age = 16;
public string Name { get; set; }
public string Query()
{
return this.GetType().ToString();
}
}
添加App.config配置项
<appSettings> <add key="DBName" value="My.Sqlserver.Dal,SqlServerHelper"/> </appSettings>
ReflectedDemo项目中Program.cs调用代码:
string str = ConfigurationManager.AppSettings["DBName"];
string strAssembly = str.Split(',')[0];
string strClass=str.Split(',')[1];
Assembly assembly = Assembly.Load(strAssembly);
Type t = assembly.GetType(strAssembly + "." + strClass);
ISqlHelper obj = Activator.CreateInstance(t) as ISqlHelper;
Console.WriteLine(obj.Query());
这样每次需要切换数据库时,只要修改配置文件就可以了。
项目结构:
注意:反射虽然很强大,但却是比较耗性能的,所以一般和缓存结合起来使用。
项目源码:ReflectedDemo.zip
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
# C#
# 程序集
# 反射
# C# 动态加载程序集信息
# C#中调用DLL时未能加载文件或程序集错误的处理方法(详解)
# C#使用反射加载多个程序集的实现方法
# C#中的程序集和反射介绍
# SQL Server中调用C#类中的方法实例(使用.NET程序集)
# C# 获取程序集版本、文件版本
# C# Assembly类访问程序集信息
# 在C#中如何获取程序集
# 来实现
# 配置文件
# 类中
# 类库
# 报错
# 会报
# 设置为
# 就可以
# 自己的
# 都是
# 加载
# 就会
# 就在
# 又是
# 你就
# 却是
# 子类
# 中有
# 目录中
# 推荐使用
相关文章:
小型网站建站如何选择虚拟主机?
网页设计与网站制作内容,怎样注册网站?
如何快速打造个性化非模板自助建站?
如何快速启动建站代理加盟业务?
南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?
陕西网站制作公司有哪些,陕西凌云电器有限公司官网?
网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?
如何快速生成橙子建站落地页链接?
视频网站app制作软件,有什么好的视频聊天网站或者软件?
如何快速搭建高效WAP手机网站吸引移动用户?
制作网站公司那家好,网络公司是做什么的?
如何在腾讯云免费申请建站?
代刷网站制作软件,别人代刷火车票靠谱吗?
如何通过FTP空间快速搭建安全高效网站?
沈阳个人网站制作公司,哪个网站能考到沈阳事业编招聘的信息?
如何批量查询域名的建站时间记录?
如何通过建站之星自助学习解决操作问题?
南宁网站建设制作定制,南宁网站建设可以定制吗?
如何通过NAT技术实现内网高效建站?
如何快速搭建安全的FTP站点?
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
如何在Golang中处理模块冲突_解决依赖版本不兼容问题
如何快速搭建高效简练网站?
购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?
建站之星后台密码遗忘或太弱?如何重置与强化?
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
测试制作网站有哪些,测试性取向的权威测试或者网站?
在线制作视频网站免费,都有哪些好的动漫网站?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
如何配置支付宝与微信支付功能?
如何配置IIS站点权限与局域网访问?
如何快速搭建高效可靠的建站解决方案?
简单实现Android文件上传
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
独立制作一个网站多少钱,建立网站需要花多少钱?
如何选择长沙网站建站模板?H5响应式与品牌定制哪个更优?
如何用虚拟主机快速搭建网站?详细步骤解析
天津个人网站制作公司,天津网约车驾驶员从业资格证官网?
如何在IIS7中新建站点?详细步骤解析
,有什么在线背英语单词效率比较高的网站?
c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】
c++怎么使用类型萃取type_traits_c++ 模板元编程类型判断【方法】
深入理解Android中的xmlns:tools属性
简历在线制作网站免费版,如何创建个人简历?
已有域名如何快速搭建专属网站?
建站10G流量真的够用吗?如何应对访问高峰?
广州营销型建站服务商推荐:技术优势与SEO优化解析
香港服务器建站指南:免备案优势与SEO优化技巧全解析
如何选择CMS系统实现快速建站与SEO优化?
*请认真填写需求信息,我们会在24小时内与您取得联系。