">>>":代表包含
进程>>>应用程序域AppDomain>>>程序集Assembly>>>模块Module>>>类型Type>>>成员(方法、属性等)
如图,假设一个解决方案里创建有多个项目:
(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的程序集
以程序集SuperControl为例,其中包含的模块只有一个SuperControl.exe的可执行程序。
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();//获取里面所有的类型
//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);
该程序使用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
}
}