马上加入IBC程序猿 各种源码随意下,各种教程随便看! 注册 每日签到 加入编程讨论群

C#教程 ASP.NET教程 C#视频教程程序源码享受不尽 C#技术求助 ASP.NET技术求助

【源码下载】 社群合作 申请版主 程序开发 【远程协助】 每天乐一乐 每日签到 【承接外包项目】 面试-葵花宝典下载

官方一群:

官方二群:

C#动态加载程序集信息

[复制链接]
查看3448 | 回复3 | 2017-3-21 09:03:56 | 显示全部楼层 |阅读模式
在设计模式的策略模式中,需要动态加载程序集信息,本文通过一个简单的实例,来讲解动态加载Dll需要的知识点。

涉及知识点:


  • AssemblyName类,完整描述程序集的唯一标识, 用来表述一个程序集。
  • Assembly类,在System.Reflection命名空间下,表示一个程序集,它是一个可重用、无版本冲突并且可自我描述的公共语言运行时应用程序构建基块。
  • Module类 表述在模块上执行反射,表述一个程序集的模块信息。
  • Type类,在System命名空间下,表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,以及开放或封闭构造的泛型类型。
  • FieldInfo类,发现字段属性并提供对字段元数据的访问权。
  • MethodInfo类,发现方法的属性并提供对方法元数据的访问。
  • EventInfo类,发现事件的属性并提供对事件元数据的访问权。
  • ConstructorInfo类,发现类构造函数的属性并提供对构造函数元数据的访问权。
  • Activator类,包含特定的方法,用以在本地或从远程创建对象类型,或获取对现有远程对象的引用。此类不能被继承。
  • BindingFlags类,指定控制绑定和由反射执行的成员和类型搜索方法的标志。在获取方法时,第二个参数会用到


如下图所示:

C#动态加载程序集信息,c#教程,c#论坛,IBC编程社区,WWW.IBCIBC.COM

C#动态加载程序集信息,c#教程,c#论坛,IBC编程社区,WWW.IBCIBC.COM



具体代码如下:

[C#] 纯文本查看 复制代码
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());
        }
    }



C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
ibcadmin | 2017-3-21 09:04:23 | 显示全部楼层
2333
C#论坛 www.ibcibc.com IBC编程社区
C#
C#论坛
IBC编程社区
Amy尾巴 | 2017-3-21 09:06:54 | 显示全部楼层
2222
言わぬが花 | 2017-3-21 09:12:19 | 显示全部楼层
2111
*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则