C#提高知识-001:反射的应用和原理(一)-创新互联

在项目中,程序集间的相互引用是经常遇到的。比如,主程序引用各分模块,各分模块引用公用程序集,以及平行的程序集间为了某些功能的实现也需要相互引用。这样的引用一方面是迫不得已的选择,而另一方面也反映出系统设计的水平。下面,简单介绍一下C#中的一种机制——反射。反射可以在避免某些情况下的程序集引用问题,比如主程序引用各功能模块的问题,当然其它模块间也是可以用反射的,只是使用是否方便这些问题需要在使用前根据实际情况进行考虑。本文以主程序加载分模块为例,介绍一下反射的使用。
所谓反射,就是对程序集或模块利用基础类型进行解析,然后还原出一个对象模型,在调用者工作域里运行的一个过程。其核心部分就是解析。工作原理是这样的。
无论你创建的多么结构复杂的类,归根结底都是由元数据构成的。如下,

目前创新互联已为上1000+的企业提供了网站建设、域名、网络空间、网站托管、服务器租用、企业网站设计、达州网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
public class Person
 {
     private string name;
     private int  age;
     private string content;
 }

在程序编译时,编译器会创建类型表,字段表,方法表或其它表。再利用System.Reflection命名空间中的包含的类型进行解析,也可以看成对比的过程,将要被反射的程序集中的表读出,根据System.Reflection的基本类型,进行重组,从而还原出原来程序集的结构。
例如,序列化的过程就是使用了反射,序列化格式器将被序列化的对象中的字段的值获取出来,然后写入一个字节流,进行传输;因为字节流传输不容易出错或信息丢失。接收到字节流后,根据基本类型再还原出原对象的模型。
反射中,System.Type类型很重要,它遍历被反射的表中的类型和反射中的基本类型进行比较,然后判断出当前是什么类型。
简单了解了原理,那么再看如何使用的。
建一个工程,包含主程序和子程序集,如图

C#提高知识-001:反射的应用和原理(一)

主程序生成在SetupApp文件夹中,子程序生成在\SetupApp\Library\中。
子程序的程序入口需要遵循一些约定,比如入口类名字需要都一样,这样才可统一加载。

namespace ReflecLibrary2
{
    public class MainWindow
    {
        public MainWindow()
        {
           welcome();
        }
        private void Welcome()
        {
            Console.Write(@"当前程序为:ReflecLibrary2 ");
            Console.WriteLine(@"开始执行ReflecLibrary2!");
        }
    }
}
namespace ReflectLibrary1
{
    public class MainWindow
    {
        public MainWindow()
        {
           welcome();
        }
        private void Welcome()
        {
            Console.Write(@"当前程序为:ReflectLibrary1 ");
            Console.WriteLine(@"开始执行ReflecLibrary1!");
        }
    }
}

然后看调用的部分,

class Program
    {
        static void Main(string[] args)
        {
            /////////////////////设置约定的规则,比如需要加载的程序的目录,程序集程序入口的类///////////////////
            string startPath = AppDomain.CurrentDomain.BaseDirectory + @"Library\";
            string suffix=@".dll";
            string commonMainClass = @"MainWindow";
            DirectoryInfo directory = new DirectoryInfo(startPath);
            /////////////////////将程序集文件名读入,这里其实只需要string类型的路径即可,
            //////为了后面处理字符串方便所以才读取文件信息
            var libraries = directory.GetFiles().OrderBy(o=>o.FullName);
            List loadDlls = new List();
            if (libraries != null)
            {
                foreach (FileInfo item in libraries)
                {
                    if (item.FullName.ToLower().EndsWith(suffix))
                    {
                        loadDlls.Add(item);
                    }
                }
            }
            /////////////////////执行程序集///////////////////
            //程序集1
            Assembly assembly1 = Assembly.LoadFile(loadDlls[0].FullName.Replace(@"/", @"\"));
            string typeName1 = loadDlls[0].Name.Replace(loadDlls[0].Extension,string.Empty) + @"." + commonMainClass;
            assembly1.CreateInstance(typeName1);
            //程序集2
            Assembly assembly2 = Assembly.LoadFile(loadDlls[1].FullName.Replace(@"/", @"\"));
            string typeName2 = loadDlls[1].Name.Replace(loadDlls[0].Extension, string.Empty) + @"." + commonMainClass;
            assembly2.CreateInstance(typeName2);
            Console.ReadLine();
        }

各个部分的作用都写在了注释中。
运行结果就是,程序集1和程序集2中的方法都执行了。当然这里只是为了方便说明只写了一个方法,实际上
public MainWindow()
{
welcome();
}
就是子程序的入口。
结果如下,

C#提高知识-001:反射的应用和原理(一)

那么反射我们就有了一个直观的理解,里面的详细原理,下一篇继续介绍

代码下载

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


文章名称:C#提高知识-001:反射的应用和原理(一)-创新互联
标题链接:http://scyanting.com/article/csscpj.html