在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载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[0].nodes.add( "基本信息" );
string dllfullname = dllassembly.fullname;
bool isglobalasseblycache = dllassembly.globalassemblycache; //是否从全局程序集加载
bool isfulltrusted = dllassembly.isfullytrusted; //是否已完全信任方式加载的
module manifestmodule = dllassembly.manifestmodule; //获取清单模块
bool isreflectiononly = dllassembly.reflectiononly; //是否加载到只反射模块中
//更新到节点
tvnodes[0].nodes[0].nodes.add( string .format( "全路径:{0}" , dllfullname));
tvnodes[0].nodes[0].nodes.add( string .format( "是否全局程序集:{0}" , isglobalasseblycache));
tvnodes[0].nodes[0].nodes.add( string .format( "是否全信任:{0}" , isfulltrusted));
tvnodes[0].nodes[0].nodes.add( string .format( "是否只反射:{0}" , isreflectiononly));
tvnodes[0].nodes[0].nodes.add( string .format( "清单模块:{0}" , manifestmodule.name));
ienumerable<type> exportedtypes = dllassembly.exportedtypes; //公共类型集合
tvnodes[0].nodes.add( "模块信息" );
int i = 0;
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[0].nodes[1].nodes.add( string .format( "模块:{0}" , modulename));
tvnodes[0].nodes[1].nodes[i].nodes.add( string .format( "数据流版本:{0}" , mdstreamversion));
tvnodes[0].nodes[1].nodes[i].nodes.add( string .format( "是否资源:{0}" , isresource));
tvnodes[0].nodes[1].nodes[i].nodes.add( string .format( "版本id:{0}" , versionid));
tvnodes[0].nodes[1].nodes[i].nodes.add( string .format( "metadata:{0}" , metadatatoken));
tvnodes[0].nodes[1].nodes[i].nodes.add( string .format( "scopename:{0}" , scopename));
tvnodes[0].nodes[1].nodes[i].nodes.add(getnodes<fieldinfo>(fields, "公共字段" ));
tvnodes[0].nodes[1].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[0].nodes.add( "类型信息" );
i = 0;
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[0].nodes[2].nodes.add( string .format( "类型:{0}" , typename));
tvnodes[0].nodes[2].nodes[i].nodes.add( string .format( "全名称:{0}" , typefullname));
tvnodes[0].nodes[2].nodes[i].nodes.add( string .format( "制定类型名称:{0}" , typeinfo.name));
tvnodes[0].nodes[2].nodes[i].nodes.add( string .format( "命名空间:{0}" , namespace ));
tvnodes[0].nodes[2].nodes[i].nodes.add( string .format( "接口:{0}" , string .join( "," , typeinterfaces.select(p => p.name))));
tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<fieldinfo>(typefields, "公共字段" ));
tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<constructorinfo>(typeconstructors, "构造函数" ));
tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<eventinfo>(typeevents, "事件" ));
tvnodes[0].nodes[2].nodes[i].nodes.add(getnodes<memberinfo>(typemembers, "成员member" ));
tvnodes[0].nodes[2].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());
}
}
动态加载和反射调用的功能还有很多,不能一一列举,只能在以后的工作中用到时再加以研究。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持服务器之家!
原文链接:http://www.cnblogs.com/hsiang/p/6505568.html
dy("nrwz");