C#详解:程序域、程序集、模块、Type、反射

总结:

">>>":代表包含
进程>>>应用程序域AppDomain>>>程序集Assembly>>>模块Module>>>类型Type>>>成员(方法、属性等)

1、程序集Assembly

如图,假设一个解决方案里创建有多个项目:
(1)SuperControl:*要启动的主项目*
(2)ClassLibrary1:主项目需要引用的自定义的类库
(3)WindowsFormsApplication1:和主项目无关,没有引用关系
(4)主项目里引用的系统的其他DLL程序集:如System.Windows.Forms
程序开始运行后,就会建立一个应用程序域,其中包含多个程序集,有(1)(2)(4)。
每个程序集可以理解为一个单独的项目。

使用Assembly.GetExecutingAssembly()可以获取当前执行代码的程序集,可以理解为获取当前的主项目SuperControl。使用AppDomain.CurrentDomain.GetAssemblies()可以获取当前应用程序域中所有用到的程序集。如下图。

补充:
如果运行的项目SuperControl中引用了类库ClassLibrary1,也引用了命名空间using ClassLibrary1。但实际代码里没有用到ClassLibrary1项目中的任何东西,使用AppDomain.CurrentDomain.GetAssemblies()就不会获取到名为ClassLibrary1的程序集

2、模块Module

以程序集SuperControl为例,其中包含的模块只有一个SuperControl.exe的可执行程序。

3、类型Type

1、就是类class,结构体struct,枚举enum等,都是属于类型Type。
2、如果用到反射就需要拿到具体的类型Type。有了类型Type就等于有了这个类内部的所有信息,以后就可以任意的动态生成一个新的实例,或者动态改变原来实例的数据。
3、如果要获取某个项目(即程序集Assembly)里面定义的类,可以用程序集Assembly,也可以用Module来获取,因为它们近乎是一个东西,单个程序集Assembly里主要的东西就是那个.exe或者.dll模块。程序集Assembly>>>模块Module。
例:

 Assembly assembly = Assembly.GetExecutingAssembly();//获取当前项目程序集
            Type[] types = assembly.GetTypes();

 Assembly assembly = Assembly.GetExecutingAssembly();//获取当前项目程序集
       Module module = assembly.GetModule("SuperControl.exe");//获取里面的模块
            types = module.GetTypes();//获取里面所有的类型

4、反射:动态生成项目SuperControl中类名为SubForm的实例

//Assembly assembly = //Assembly.LoadFrom(@"C:\Users\Administrator\Desktop\TEST\ControlMoveTEST\SuperControl\
//SuperControl\bin\Debug\SuperControl");

  Assembly asy = Assembly.GetExecutingAssembly();
  object obj = asy.CreateInstance("SuperControl.SubForm");//填类型全名,包括命名空间
//如果要操作其他的项目程序集里的内容,就获取别的项目的Assembly。

//(1)显示窗体方式1
	((SubForm)obj).Show();//显示窗体
//(2)显示窗体方式2
   Type typeInfo = asy.GetType("SuperControl.SubForm");//填类型全名,包括命名空间
   MethodInfo minfo = typeInfo.GetMethod("Show",new Type[]{});//显示窗体1
   minfo.Invoke(obj, null);//显示窗体2
//(3) 设置窗体的启动位置
   typeInfo.GetProperty("StartPosition").SetValue(obj, FormStartPosition.CenterScreen);

5、反射案例

该程序使用CreateControl()方法,根据用户的选择动态生成所需要的控件:FlowLayoutPanel,Button,Label

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace SuperControl
{
    public partial class SubForm : DockContent
    {
        public SubForm()
        {
            InitializeComponent();

            this.ContextMenuStrip = contextMenuStrip1;
        }




        private void layoutPanelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateControl(typeof(FlowLayoutPanel), "fpanel");
        }

        private void buttonToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateControl(typeof(Button), "btn");
        }

        private void labelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            CreateControl(typeof(Label), "text");
        }

        public void obj_MouseDown(object sender, MouseEventArgs e)
        {
            MoveControl(sender as Control, e);
        }

        public void CreateControl(Type tp, string text)
        {
            // object obj = Assembly.GetExecutingAssembly().CreateInstance(tp.FullName); //不能用这个,因为该类型不是在当前程序集里                
             
            //方法一、
            object obj = Activator.CreateInstance(tp); //这个可以,应该是自动获取了必要的信息

            //方法二、
       //object obj =                 
      //AppDomain.CurrentDomain.CreateInstanceAndUnwrap("System.Windows.Forms,             
     //Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", tp.FullName);


            tp.GetProperty("Text").SetValue(obj, text); //设置Text
            tp.GetEvent("MouseDown").AddEventHandler(obj, new MouseEventHandler(obj_MouseDown)); //注册事件
            Point p = PointToClient(new Point(Control.MousePosition.X - 20, Control.MousePosition.Y - 10));
            tp.GetProperty("Location").SetValue(obj, p); //设置显示位置
            if (tp == typeof(FlowLayoutPanel))
            {
                tp.GetProperty("BorderStyle").SetValue(obj, BorderStyle.FixedSingle); //设置控件边框

            }
            this.Controls.Add(obj as Control); //将生成的控件添加到界面
        }






        #region 控件移动API


        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool ReleaseCapture();

        private void MoveControl(Control sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && e.Clicks == 1)
            {
                ReleaseCapture();
                SendMessage(sender.Handle, 161, 2, 0);
                SendMessage(sender.Handle, 0x0202, 0, 0);
            }
            else
            {
                //添加双击或右击代码……
            }
        }


        #endregion


    }
}

猜你喜欢

转载自blog.csdn.net/stephon_100/article/details/128152503