C# 动态加载程序集信息
本文通过一个简单的实例,来讲解动态加载Dll需要的知识点。仅供学习分享使用,如有不足之处,还请指正。
在设计模式的策略模式中,需要动态加载程序集信息。
涉及知识点:
- AssemblyName类,完整描述程序集的唯一标识, 用来表述一个程序集。
- Assembly类,在System.Reflection命名空间下,表示一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行时应用程序构建基块。
- Module类 表述在模块上执行反射,表述一个程序集的模块信息。
- Type类,在System命名空间下,表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
- FieldInfo类,发现字段属性并提供对字段元数据的访问权。
- MethodInfo类,发现方法的属性并提供对方法元数据的访问。
- EventInfo类,发现事件的属性并提供对事件元数据的访问权。
- ConstructorInfo类,发现类构造函数的属性并提供对构造函数元数据的访问权。
- Activator类,包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。此类不能被继承。
- BindingFlags类,指定控制绑定和由反射执行的成员和类型搜索方法的标志。在获取方法时,第二个参数会用到
效果图
如下图所示:
核心代码
具体代码如下:
public partial class DllLoadForm : Form
{
public DllLoadForm()
{
InitializeComponent();
} private void btnOpenFile_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog()
{
Multiselect=false,
Filter = "Dll Info|*.dll|All Files|*.*",
InitialDirectory=AppDomain.CurrentDomain.BaseDirectory,
Title="Dll信息",
Tag="请选择"
};
if (ofd.ShowDialog() == DialogResult.OK) {
this.txtDllFile.Text = ofd.FileName;
}
} private void btnLoadDll_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(this.txtDllFile.Text.Trim())) {
MessageBox.Show("请选择dll文件");
return;
}
LoadDllInfo(this.txtDllFile.Text);
} /// <summary>
/// 动态加载Dll
/// </summary>
/// <param name="dllPath">需要加载的Dll的路径</param>
public void LoadDllInfo(string dllPath)
{
if (File.Exists(dllPath))
{
TreeNodeCollection tvNodes = tvDllInfo.Nodes;
tvNodes.Clear();
tvNodes.Add("DllInfo");
AssemblyName dllAssemblyName = AssemblyName.GetAssemblyName(dllPath);
Assembly dllAssembly = Assembly.Load(dllAssemblyName);
Module[] modules = dllAssembly.GetModules();//获取作为程序集一部分的所有模块信息
Type[] types = dllAssembly.GetTypes();//获取程序集中定义的所有类型
AssemblyName[] referrenceAsseblies = dllAssembly.GetReferencedAssemblies();//获取程序集引用的程序集信息
tvNodes[].Nodes.Add("基本信息"); string dllFullName = dllAssembly.FullName;
bool isGlobalAsseblyCache = dllAssembly.GlobalAssemblyCache;//是否从全局程序集加载
bool isFullTrusted = dllAssembly.IsFullyTrusted;//是否已完全信任方式加载的
Module manifestModule = dllAssembly.ManifestModule;//获取清单模块
bool isReflectionOnly = dllAssembly.ReflectionOnly;//是否加载到只反射模块中
//更新到节点
tvNodes[].Nodes[].Nodes.Add(string.Format("全路径:{0}", dllFullName));
tvNodes[].Nodes[].Nodes.Add(string.Format("是否全局程序集:{0}", isGlobalAsseblyCache));
tvNodes[].Nodes[].Nodes.Add(string.Format("是否全信任:{0}", isFullTrusted));
tvNodes[].Nodes[].Nodes.Add(string.Format("是否只反射:{0}", isReflectionOnly));
tvNodes[].Nodes[].Nodes.Add(string.Format("清单模块:{0}", manifestModule.Name));
IEnumerable<Type> exportedTypes = dllAssembly.ExportedTypes;//公共类型集合
tvNodes[].Nodes.Add("模块信息");
int i = ;
foreach (var module in modules)
{
FieldInfo[] fields = module.GetFields();//返回模块中定义的全局字段
MethodInfo[] methods = module.GetMethods();//返回模块中定义的全局方法
Type[] mtypes = module.GetTypes();//返回模块中定义的类型集合
bool isResource = module.IsResource();//指示此模块是否是资源
int mdStreamVersion = module.MDStreamVersion;//获取源数据流的版本
Guid versionId = module.ModuleVersionId;//获取模块的版本ID
string moduleName = module.Name;//获取模块的名称,去除路径的
int metadataToken = module.MetadataToken;
string scopeName = module.ScopeName;
tvNodes[].Nodes[].Nodes.Add(string.Format("模块:{0}", moduleName));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("数据流版本:{0}", mdStreamVersion));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("是否资源:{0}", isResource));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("版本ID:{0}", versionId));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("MetaData:{0}", metadataToken));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("ScopeName:{0}", scopeName));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<FieldInfo>(fields, "公共字段"));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<MethodInfo>(methods, "Mehods"));
//tvNodes[0].Nodes[1].Nodes[i].Nodes.Add(string.Format("Types:{0}", string.Join(",", mtypes.Select(p => p.Name))));
i++;
}
tvNodes[].Nodes.Add("类型信息");
i = ;
foreach (var type in types)
{
TypeAttributes typeAttributes = type.Attributes;//与Type关联的属性
string typeFullName = type.FullName;//获取类型的完全限定名称
FieldInfo[] typeFields = type.GetFields();//获取所有的公共字段
EventInfo[] typeEvents = type.GetEvents();//获取所有的 公共事件
Type[] typeInterfaces = type.GetInterfaces();//获取所有的公共接口
MemberInfo[] typeMembers = type.GetMembers();//获取所有的公共成员
MethodInfo[] typeMethods = type.GetMethods();//获取所有的公共方法
TypeInfo typeInfo = type.GetTypeInfo();//返回指定类型的表述形式
string nameSpace = type.Namespace; //指定类型的命名空间
string typeName = type.Name;//获取当前成员的名称
ConstructorInfo[] typeConstructors = type.GetConstructors();//类型的构造函数
tvNodes[].Nodes[].Nodes.Add(string.Format("类型:{0}", typeName));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("全名称:{0}", typeFullName));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("制定类型名称:{0}", typeInfo.Name));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("命名空间:{0}", nameSpace));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(string.Format("接口:{0}", string.Join(",", typeInterfaces.Select(p => p.Name))));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<FieldInfo>(typeFields, "公共字段"));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<ConstructorInfo>(typeConstructors, "构造函数"));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<EventInfo>(typeEvents, "事件"));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<MemberInfo>(typeMembers, "成员Member"));
tvNodes[].Nodes[].Nodes[i].Nodes.Add(GetNodes<MethodInfo>(typeMethods, "公共方法"));
i++; }
}
} /// <summary>
/// 通过类型获取节点
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="lstInfos"></param>
/// <param name="name"></param>
/// <returns></returns>
public TreeNode GetNodes<T>(T[] lstInfos, string name) where T : MemberInfo
{
TreeNode tNode = new TreeNode(name);
foreach (var t in lstInfos)
{
tNode.Nodes.Add(t.Name);
}
return tNode;
} /// <summary>
/// 调用静态方法的例子
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCallStaticByReflection_Click(object sender, EventArgs e)
{
AssemblyName assemblyName = AssemblyName.GetAssemblyName("TestAssembly.exe");
Assembly assembly = Assembly.Load(assemblyName);
Type t = assembly.GetType("TestAssembly.Program", true, true);
//object o= Activator.CreateInstance(t, false);
MethodInfo methodInfo = t.GetMethod("Main",BindingFlags.Static|BindingFlags.Public);
methodInfo.Invoke(null,new string[][] { new string[] { "g" } }); } /// <summary>
/// 调用非静态方法的例子
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnCallFunctionByReflection_Click(object sender, EventArgs e)
{
AssemblyName assemblyName = AssemblyName.GetAssemblyName("TestAssembly.exe");//此处是相对路径
Assembly assembly = Assembly.Load(assemblyName);
Type t = assembly.GetType("TestAssembly.Program", true, true);
object o = Activator.CreateInstance(t, false);
MethodInfo methodInfo = t.GetMethod("TestAssembly", BindingFlags.Instance|BindingFlags.Public);
object tmp= methodInfo.Invoke(o,null);
MessageBox.Show(tmp.ToString());
}
}
----------------------------------------------------------------------
动态加载和反射调用的功能还有很多,不能一一列举,只能在以后的工作中用到时再加以研究。
C# 动态加载程序集信息的更多相关文章
- C# 动态加载程序集dll (实现接口)
一.程序集(接口程序集):LyhInterface.Dll namespace LyhInterface { public interface ILyhInterface { void Run(); ...
- C#动态加载程序集(转)
C#动态加载程序集 今天在看网络上的一篇关于‘.NET应用自动部署窗体技术’.NET的自动部署技术构造在.NET框架之中,它使得应用程序能够通过HTTP连接从远程服 务器按需下载程序集.有了这个功能, ...
- .Net Core 通过依赖注入和动态加载程序集实现宿程序和接口实现类库完全解构
网上很多.Net Core依赖注入的例子代码,例如再宿主程序中要这样写: services.AddTransient<Interface1, Class1>(); 其中Interface1 ...
- 应用程序域 System.AppDomain,动态加载程序集
一.概述 使用.NET建立的可执行程序 *.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中.在一个进程中可以包含多个应用程序域,一个应用程序域可以装载一个可执行程序( ...
- C# 反射实现动态加载程序集
原文:https://blog.csdn.net/pengdayong77/article/details/47622235 在.Net 中,程序集(Assembly)中保存了元数据(MetaData ...
- 关于c#动态加载程序集的一些注意事项
Assembly下有LoadFile,LoadFrom等方法可以加载程序集. LoadFile只加载你给定路径的那个dll,LoadFrom会自动加载依赖的dll. 如:A依赖B,LoadFile(& ...
- Unity 5.x动态加载光照信息(所有坑已踩)
能搜到这的应该是被新的烘焙系统坑了少时间,4.x到5.x美术必须重新烘焙,关于美术的没什么说的,只有---重新烘焙! 新的烘焙系统,为了兼容5.x的多场景编辑功能,将烘焙信息从mesh全部挪到了一个中 ...
- Assembly.Load动态加载程序集而不占用文件 z
方式一:占用文件的加载 Assembly assembly = Assembly.Load(path); 用上面的方法可以动态的加载到dll,但是用这种方法加载到的dll一直到程序运行结束都是占用的d ...
- asp.net动态加载程序集创建指定类的实例及调用指定方法
以下类中有三个方法: LoadAssembly:加载指定路径的程序集 GetInstance:根据Type动态获取实例,用泛型接到返回的类型 ExecuteMothod:执行实例中的指定方法 /// ...
随机推荐
- Redis 常用操作命令,非常详细!
下面总结并演示了 Redis 的 常用管理命令.key 操作.字符串.集合.列表.散列类型的操作命令. 你需要掌握的 Redis 知识 史上最全 Redis 高可用解决方案总结 为什么分布式一定要有R ...
- iview导航菜单updateOpened和updateActiveName的使用
先看官方文档: iview导航菜单 这里主要遇到的问题有两个: 1. 点击回到首页(B按钮)时需要取消选中当前选中的菜单项(全部不选中),这里用到的是 updateActiveName方法 2. 点击 ...
- Lombok的@Data、@Setter、@Getter注解没反应问题解决
在用@Data注解时,没有生成setter/getter方法.百度了一堆都没解决方法,后来用Google查了一下解决了~~~ 使用IDEA需要安装Lombok插件,我这里已经下载好,如果没下载安装点击 ...
- CentOS 7.x 安装 Docker-Compose
一.安装步骤 添加企业版附加包. yum -y install epel-release 安装 PIP. yum -y install python-pip 更新 PIP. pip install - ...
- Spring IOC分析
前言 关于Spring,我想无需做太多的解释了.每个Java程序猿应该都使用过他.Spring的ioc和aop极大的方便了我们的开发,但是Spring又有着不好的一面,为了符合开闭原则,Spring的 ...
- 开源任务调度平台elastic-job-lite源码解析
前段时间写过一遍文章<一文揭秘定时任务调度框架quartz>,有读者建议我再讲讲elastic-job这个任务调度框架,年末没有那么忙,就来学习一下elastic-job. 首先一点,el ...
- greenev —— Python 异步网络服务框架
greenev是一个基于greenlet协程,事件驱动,非阻塞socket模型的Python网络服务框架,它使得可以编写同步的代码,却得到异步执行的优点. 本项目受到gevent, openresty ...
- 网络协议抓包分析——IP互联网协议
前言 IP协议是位于OSI模型的第三层协议,其主要目的就是使得网络间可以相互通信.在这一层上运行的协议不止IP协议,但是使用最为广泛的就是互联网协议. 什么是IP数据报 TCP/IP协议定义了一个在因 ...
- 【Go】go get 自动代理
原文链接:https://blog.thinkeridea.com/201903/go/go_get_proxy.html 最近发现技术交流群里很多人在询问 go get 墙外包失败的问题,大家给了很 ...
- SpringBoot之Swagger2的使用
Swagger是一组围绕OpenAPI规范构建的开源工具,可帮助设计.构建.记录和使用REST API.简单说下,它的出现就是为了方便进行测试后台的restful形式的接口,实现动态的更新,当我们在后 ...