利用C#中的反射机制回实现关机插件
插件编程技术
插件是指遵循一定的接口规范、可以动态加载和运行的程序模块。利用反射的动态加载代码能力,可以很容易的实现插件,
插件编程的要点是使用接口来定义插件的功能特征。插件的宿主程序通过接口来确认、装载和执行插件的功能,实现插件功能的所有类都必须实现定义插件的接口。
1、首先定义一个关机的接口 IShut,生成程序集,并在UI层(Winform窗体)来添加引用
public interface IShut
{
string Name { get; }
void ShutDownCPU(int time);
}
2、再通过一个类ShutDownClass 来实现接口IShut,并生成程序集,
以后就通过实现接口IShut来实现更多的功能:
class ShutDownClass : IShut
{
public string Name
{
get { return "关机插件"; }
}
public void ShutDownCPU(int time)
{
ShutDown(time);
}
public void ShutDown(int second)
{
//以下来设置关机的一些属性
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
process.StandardInput.WriteLine("shutdown -s -f -t " + second);
//process.StandardInput.WriteLine("dir c:");
process.StandardInput.WriteLine("exit");
process.Close();
process.Dispose();
}
}
3、UI是通过Winform来实现的,也就通过一个控件ToolStripMenuItem
UI层是通过反射来获得ShutDownClass.dll的程序集 中的类,成员,属性
通过 GetTypes()方法可以获得程序集中的所有成员
Assembly ass = Assembly.LoadFile(item);
//获得程序集中的成员
Type[] types = ass.GetTypes();
通过 Activator.CreateInstance()可以获得Type类中的对象,返回的object类型
需传入Type类型
用法:
//创建对象
IShut shut = Activator.CreateInstance(types[i]) as IShut;
Type类:
---->IsAssignableFrom()函数,判断某一个类是否可以赋值给另一个类。是否符合里氏代换的原则!
---->IsInstanceOfType()函数,判断是否是指定类的实例。
---->IsSubclassOf()函数,判断是否是某个类的子类,注意!!!没有接口的事儿!!!!
---->IsAbstract()函数,判断某一个类是否是抽象的。
用法:
if (typeof(IShut).IsAssignableFrom(types[i]) && !types[i].IsAbstract)
UI层的代码
private void Form1_Load(object sender, EventArgs e)
{
//功能ToolStripMenuItem.DropDown.Items.Add("关机");
//功能ToolStripMenuItem.DropDown.Items.Add("重启");
//获得plug文件夹的全路径
string path = Path.GetFullPath("plug");
//获得plug文件夹中所有的文件
string[] files = Directory.GetFiles(path, "*.dll");
//遍历files
foreach (string item in files)
{
//item:dll文件的绝对路径
Assembly ass = Assembly.LoadFile(item);
//获得程序集中的成员
Type[] types = ass.GetTypes();
//判断是否是我们需要的成员
for (int i = 0; i < types.Length; i++)
{
if (typeof(IShut).IsAssignableFrom(types[i]) && !types[i].IsAbstract)
{
//当前的数据使我们需要的数据
//创建对象
IShut shut = Activator.CreateInstance(types[i]) as IShut;
//创建菜单
ToolStripItem tsi = 功能ToolStripMenuItem.DropDown.Items.Add(shut.Name);
//存储shut
tsi.Tag = shut;
//注册单击事件
tsi.Click += tsi_Click;
}
}
}
}
void tsi_Click(object sender, EventArgs e)
{
ToolStripItem tsi = sender as ToolStripItem;
IShut s = tsi.Tag as IShut;
s.ShutDownCPU(1200);
}
扩展:
如果需动态调用类中的成员:(也是Type类中的方法 )
MemberInfo:抽象父类
PropertyInfo:获取属性
MethodInfo:获取方法
FieldInfo:获取字段
EventInfo:获取事件
用法:
//获得单个的数据成员
Assembly ass = Assembly.LoadFile(Path.GetFullPath("Common.dll"));
//获得程序集中Person类型信息
Type t = ass.GetType("Common.Person");
//创建Person类对象o
//object o = ass.CreateInstance("Common.Person");
//获得类中的单个成员方法
MethodInfo m = t.GetMethod("SayHello");
////调用方法
m.Invoke(o, null);
- 2楼跋锋寒LT
- 发射真的很重要
- 1楼沈赟
- 谢谢分享