C# 程序集(Assembly)
<h2><span style="font-family: 幼圆">程序集</span></h2><p><span style="font-family: 幼圆; font-size: 15px">程序集是代码进行编译是的一个逻辑单元,把相关的代码和类型进行组合,然后生成PE文件。程序集只是逻辑上的划分,一个程序集可以只由一个文件组成,也可由多个文件组成。不管是单文件程序集还是多文件程序集,它们都由固定的结构组成</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">常见的两种程序集:</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px"> 可执行文件(.exe文件)和 类库文件(.dll文件)。</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">在VS开发环境中,一个解决方案可以包含多个项目,而每个项目就是一个程序集。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">应用程序结构:</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px"> 包含 应用程序域(AppDomain),程序集(Assembly),模块(Module),类型(Type),成员(EventInfo、FieldInfo、MethodInfo、PropertyInfo) 几个层次</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">他们之间是一种从属关系,也就是说,一个AppDomain能够包括N个Assembly,一个Assembly能够包括N个Module,一个Module能够包括N个Type,一个Type能够包括N个成员。他们都在System.Reflection命名空间下。【公共语言运行库CLR】加载器 管理 应用程序域,这种管理包括 将每个程序集加载到相应的应用程序域 以及 控制每个程序集中类型层次结构的内存布局</span></p>
<p><span style="font-family: 幼圆; font-size: 15px">从【应用程序结构】中不难看出程序集Assembly的组成:</span></p>
<p><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191213170622555-1910463621.png" alt=""></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">MemberInfo 该类是一个基类,它定义了EventInfo、FieldInfo、MethodInfo、PropertyInfo的多个公用行为 </span></p>
<p><span style="font-family: 幼圆; font-size: 15px" data-wiz-span="data-wiz-span">一个程序运行起来以后,有一个应用程序域(AppDomain),在这个应用程序域(AppDomain)中放了我们用到的所有程序集(Assembly)。我们所写的所有代码都会编译到<span data-wiz-span="data-wiz-span">【程序集】文件(.exe .dll)中,<span data-wiz-span="data-wiz-span">并在运行时以<span data-wiz-span="data-wiz-span">【Assembly对象】<span data-wiz-span="data-wiz-span">方式加载到内存中运行,每个类(Class Interface)以【Type对象】方式加载<span data-wiz-span="data-wiz-span"><span data-wiz-span="data-wiz-span"><span data-wiz-span="data-wiz-span">到内<span data-wiz-span="data-wiz-span"><span data-wiz-span="data-wiz-span"><span data-wiz-span="data-wiz-span">存,类的成员(方法,字段,属<span data-wiz-span="data-wiz-span"><span data-wiz-span="data-wiz-span"><span data-wiz-span="data-wiz-span">性,事件,构造器)加载到内存也有相应的对象。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p><span style="font-family: 幼圆; font-size: 15px">详细:https://www.cnblogs.com/luna-hehe/p/10143748.html</span></p>
<h2><span style="font-family: 幼圆">程序集的结构:</span></h2>
<p><span style="font-family: 幼圆; font-size: 15px">程序集元数据,类型元数据,MSIL代码,资源。</span></p>
<p class="a"><span style="font-family: 幼圆; font-size: 15px"><strong>①</strong><strong>程序集元数据</strong>,程序集元数据也叫清单,它记录了程序集的许多重要信息,是程序集进行自我说明的核心文档。当程序运行时,CLR 通过这份清单就能获取运行程序集所必需的全部信息。清单中主要主要包含如下信息:标识信息(包括程序集的名称、版本、文化和公钥等);文件列表(程序集由哪些文件组成);引用程序集列表(该程序集所引用的其他程序集);一组许可请求(运行这个程序集需要的许可)。</span></p>
<p class="a"><span style="font-family: 幼圆; font-size: 15px"><strong>②</strong><strong>类型元数据</strong>,类型元数据列举了程序集中包含的类型信息,详细说明了程序集中定义了哪些类,每个类包含哪些属性和方法,每个方法有哪些参数和返回值类型,等等。</span></p>
<p class="a"><span style="font-family: 幼圆; font-size: 15px"><strong>③</strong><strong>MSIL</strong><strong>代码</strong>,程序集元数据和类型元数据只是一些辅助性的说明信息,它们都是为描述MSIL代码而存在的。MSIL 代码是程序集的真正核心部分,正是它们实现了程序集的功能。比如在“Animals”项目中,五个动物类的C#代码最终都被转换为MSIL 代码,保存在程序集Animals.dll 中,当运行程序时,就是通过这些MSIL 代码绘制动物图像的。</span></p>
<p class="a"><span style="font-family: 幼圆; font-size: 15px"><strong>④</strong><strong>资源</strong>,程序集中还可能包含图像、图标、声音等资源。</span></p>
<h2><span style="font-family: 幼圆">私有程序集和共享程序集</span></h2>
<p class="a"><span style="font-family: 幼圆; font-size: 15px">私有程序集是仅供单个软件使用的程序集,安装很简单,只需把私有程序集复制到软件包所在文件夹中即可。而那些被不同软件共同使用的程序就是共享程序集,.NET类库的程序集就是共享程序集,共享程序集为不同的程序所共用,所以它的部署就不像私有程序集那么简单,必须考虑命名冲突和版本冲突等问题。解决这些问题的办法是把共享程序集放在系统的一个特定文件夹内,这个特定文件夹称为全局程序集高速缓存(GAC)。这个过程可用专门的.NET 工具完成</span></p>
<h2><span style="font-family: 幼圆">程序集的特性</span></h2>
<p class="a"><span style="font-family: 幼圆; font-size: 15px"><img src="https://img2018.cnblogs.com/i-beta/1146926/201912/1146926-20191213171719416-369295763.png" alt=""></span></p>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将 ComVisible 设置为 false 使此程序集中的类型对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,则将该类型上的 ComVisible 属性设置为 true。</span><span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果此项目向 COM 公开,则下列 GUID 是用于类型库的 ID</span><span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 程序集的版本信息由下面四个值组成:主版本、次版本、内部版本号、修订号</span><span style="color: rgba(0, 0, 0, 1)">
</span></pre>
</div>
<p><span style="font-family: 幼圆; font-size: 15px">程序集的属性信息是由特性实现的,与普通特性的不同的是,描述程序集的特性前要添加前缀“assembly:”</span></p>
<p class="a"><span style="font-family: 幼圆; font-size: 15px">原文链接:https://www.cnblogs.com/Sweepingmonk/p/10867975.html</span></p>
<div>
<h2><span style="font-family: 幼圆">Assembly 程序集对象</span></h2>
</div>
<p><strong><span style="font-family: 幼圆; font-size: 15px">Assembly 是一个抽象类,我们用的都是RuntimeAssembly的对象。</span></strong></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">获得程序集的方式:</span></strong></p>
<ul>
<li><span style="font-family: 幼圆; font-size: 15px">获得当前程序域中的所有程序集</span>
<ul>
<li>Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies();</li>
<li>所有用到过得aessembly。如果只是add ref了,没有在程序中用到,AppDomain.CurrentDomain.GetAssemblies()中没有。用到时才被JIT加载到内存。</li>
<li>每个app都有一个AppDomain,OS不允许其他app访问这个程序的AppDomain</li>
</ul>
</li>
<li><span style="font-family: 幼圆; font-size: 15px">获得当前对象所属的类所在的程序集</span>
<ul>
<li>this.GetType().Assembly;</li>
<li>Type对象肯定在一个assembly对象中</li>
<li>可以通过Type对象得到程序集</li>
</ul>
</li>
</ul>
<ul>
<li>
<p>根据路径加载程序集</p>
<ul>
<li>Assembly.LoadFrom(assPath);</li>
</ul>
</li>
</ul>
<div class="cnblogs_code">
<pre><span style="font-family: 幼圆; font-size: 15px">Assembly assembly = Assembly.LoadFrom(<span style="color: rgba(128, 0, 0, 1)">@"</span><span style="color: rgba(128, 0, 0, 1)">E:\Work\VSCode\ConsoleApp1\ClassLibrary1\bin\Debug\netstandard2.0\ClassLibrary1.dll</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
Type[] allTypes </span>=<span style="color: rgba(0, 0, 0, 1)"> assembly.GetTypes();
Type stu </span>= assembly.GetType(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ClassLibrary1.Student</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">object</span> stu1 =<span style="color: rgba(0, 0, 0, 1)"> Activator.CreateInstance(stu);
Console.WriteLine(stu1);</span></span></pre>
</div>
<h2><span style="font-family: 幼圆">Type 类型对象</span></h2>
<p><strong><span style="font-family: 幼圆; font-size: 15px">Type 是一个抽象类,我们用的都是TypeInfo类的对象。</span></strong></p>
<p><span style="font-family: 幼圆; font-size: 15px">程序运行时,一个class对应一个Type类的对象。通过Type对象可以获得类的所有信息。</span></p>
<p><strong><span style="font-family: 幼圆; font-size: 15px">获得Type对象的方式:</span></strong></p>
<ul>
<li><span style="font-family: 幼圆; font-size: 15px">通过类获得对应的Type</span>
<ul>
<li><span style="font-family: 幼圆; font-size: 15px">Type t1 = typeof(Person);</span></li>
</ul>
</li>
<li><span style="font-family: 幼圆; font-size: 15px">通过对象获得Type用assembly对象,通过类的full name类获得type对象</span>
<ul>
<li><span style="font-family: 幼圆; font-size: 15px">Type t2 = person.GetType(); </span></li>
<li><span style="font-family: 幼圆; font-size: 15px">this.GetType();</span></li>
<li><span style="font-family: 幼圆; font-size: 15px">Type stu = assembly.GetType("ClassLibrary1.Student");</span></li>
</ul>
</li>
</ul>
<ul>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">获得程序集中定义的所有的public类</span></p>
<ul>
<li><span style="font-family: 幼圆; font-size: 15px">Type[] allPublicTypes = ass1.GetExportedTypes();</span></li>
</ul>
</li>
<li>
<p>获得程序集中定义的所有的类</p>
<ul>
<li>Type[] allTypes = ass1.GetTypes();</li>
</ul>
</li>
</ul>
<h3><span style="font-family: 幼圆">Type类的属性:</span></h3>
<ul>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.Assembly; 获取t所在的程序集</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.FullName; 获取t所对应的类的full name</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.Name; 获取t所对应的类的 name</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.IsArray; 判断t是否是一个数组类</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.IsEnum; 判断t是否是一个枚举类</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.IsAbstract; 判断t是否是一个抽象类</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.IsInterface; 判断t是否是一个interface</span></p>
</li>
</ul>
<h3><span style="font-family: 幼圆">Type类的方法:</span></h3>
<p><span style="font-family: 幼圆"><img src="https://img2018.cnblogs.com/common/1146926/201912/1146926-20191217163250665-1225957363.png" alt=""></span></p>
<ul>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">notebookInterfaceType.IsAssignableFrom(Type t);判断t是否实现了 notebookInterfaceType 接口</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.IsSubclassOf(Type parent); t是否是parent的子类</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.IsInstanceOfType(object o); o是否是t类的对象</span></p>
</li>
<li>
<p><span style="font-family: 幼圆; font-size: 15px">t.GetFields(); //method, property 得到所有的public的fields,methods,properties</span></p>
</li>
</ul>
<h3><span style="font-family: 幼圆">Type类示例:</span></h3>
<div class="cnblogs_code"><span style="font-family: 幼圆"><img src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt="" id="code_img_closed_fc89ef9e-c691-40c5-bf68-e646afa446e8" class="code_img_closed"><img src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="" id="code_img_opened_fc89ef9e-c691-40c5-bf68-e646afa446e8" class="code_img_opened" style="display: none"></span>
<div id="cnblogs_code_open_fc89ef9e-c691-40c5-bf68-e646afa446e8" class="cnblogs_code_hide">
<pre><span style="font-family: 幼圆; font-size: 15px"><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> TypeTest1()
{
Person p </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Person { Name = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">NaNa</span><span style="color: rgba(128, 0, 0, 1)">"</span>, Age = <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)"> };
Type typePerson </span>=<span style="color: rgba(0, 0, 0, 1)"> p.GetType();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">搜索具有指定名称的公共属性</span>
PropertyInfo pf = typePerson.GetProperty(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Name</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
pf.SetValue(p, </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">LiLi</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">);
Console.WriteLine(p.Name);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回所有公共属性</span>
PropertyInfo[] props =<span style="color: rgba(0, 0, 0, 1)"> typePerson.GetProperties();
StringBuilder builder </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> StringBuilder(<span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (PropertyInfo item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> props)
{
builder.Append(item.Name </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">=</span><span style="color: rgba(128, 0, 0, 1)">"</span> + item.GetValue(p, <span style="color: rgba(0, 0, 255, 1)">null</span>) + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
builder.Append(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">----------------------\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回所有公共字段</span>
FieldInfo[] fieIds =<span style="color: rgba(0, 0, 0, 1)"> typePerson.GetFields();
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (FieldInfo item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> fieIds)
{
builder.Append(item.Name </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">=</span><span style="color: rgba(128, 0, 0, 1)">"</span> + item.GetValue(p) + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
builder.Append(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">----------------------\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回所有公共方法</span>
MethodInfo[] methods =<span style="color: rgba(0, 0, 0, 1)"> typePerson.GetMethods();
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (MethodInfo item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> methods)
{
builder.Append(item </span>+ <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
builder.Append(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">----------------------\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
Console.WriteLine(builder);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">返回所有公共构造函数</span>
ConstructorInfo[] cons =<span style="color: rgba(0, 0, 0, 1)"> typePerson.GetConstructors();
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (ConstructorInfo item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> cons)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Name都是 .ctor</span>
Console.WriteLine(item.Name + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">构造函数的参数个数</span>
Console.WriteLine(item.GetParameters().Length + <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
ParameterInfo[] parames </span>=<span style="color: rgba(0, 0, 0, 1)"> item.GetParameters();
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> pars <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> parames)
{
Console.WriteLine(pars.Name</span>+<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">:</span><span style="color: rgba(128, 0, 0, 1)">"</span>+<span style="color: rgba(0, 0, 0, 1)">pars.ParameterType);
}
}
}</span></span></pre>
</div>
<span class="cnblogs_code_collapse" style="font-family: 幼圆; font-size: 15px">View Code</span></div>
<p class="a"><span style="font-family: 幼圆; font-size: 15px">原文链接:https://blog.csdn.net/CJB_King/article/details/80521481</span></p><br><br>
来源:https://www.cnblogs.com/zhaoyl9/p/12036037.html
頁:
[1]