cad.net IExtensionApplication接口的妙用 分开写"启动运行"函数
cad提供的 IExtensionApplication 接口 是不能实现一次以上的,那么这给编写代码带来了一种不好的情况是,每次都要去修改实现这个接口的类,
如果是一个小的测试功能,你又要去动前面的核心,这样就感觉很蛋疼....编程思维上面叫做"开闭原则":对拓展进行开放,对修改进行关闭.
所以我是这么想的,在实现IExtensionApplication接口的 Initialize 和 Terminate 时候,
用反射来找到某个接口(仿IExtensionApplication接口的),然后搜下面接口的 Initialize 和 Terminate,然后运行这个它.
20191227增加了控制加载顺序的函数
仿IExtensionApplication接口的接口.
/// <summary>
/// 控制加载顺序
/// </summary>
public enum Sequence : byte
{
First,// 最先
Last, // 最后
} public interface IAutoGo
{
// 控制加载顺序
Sequence SequenceId(); // 关闭cad的时候会自动执行
void Terminate(); //打开cad的时候会自动执行
void Initialize();
}
继承 IExtensionApplication 接口的函数,cad加载这个dll,就会运行它.
class RunClass
{
Type _ty;
public string NamePace { get; private set; }
public string ClassName { get; private set; }
public Sequence SequenceId
{
get
{
Sequence sequence = Sequence.Last;
try
{
string sequenceId = "SequenceId";
_ty = Assembly.Load(NamePace).GetType(ClassName); //加载命名空间下的class
MethodInfo method = _ty.GetMethod(sequenceId); //获取这个class的方法 //居然是静态获取返回的枚举值
object instanceObject = Activator.CreateInstance(_ty);
object returnValue1 = method.Invoke(instanceObject, null); //运行
sequence = (Sequence)returnValue1;
}
catch
{ }
return sequence;
}
} public RunClass(string namePace, string className)
{
NamePace = namePace;
ClassName = className;
} public void Run(string methodInfoName)
{
try
{
MethodInfo method = _ty.GetMethod(methodInfoName); //获取这个class的方法
if (method.IsStatic)//判断是否静态方法
{
method.Invoke(null, null);//静态调用
}
else //非静态,调用实例化方法
{
object instanceObject = Activator.CreateInstance(_ty);
object returnValue1 = method.Invoke(instanceObject, null); //运行
}
}
catch (System.Exception)
{
throw;
}
}
} //为了解决IExtensionApplication在一个dll内无法多次实现接口的关系
//所以在这里反射加载所有的IAutoGo,以达到能分开写"启动运行"函数的目的
public class AutoClass : IExtensionApplication
{
//打开cad的时候会自动执行
public void Initialize()
{
RunIAutoGo("Initialize");
} //关闭cad的时候会自动执行
public void Terminate()
{
//可以用
//MessageBox.Show("哇哇哇哇哇"); //不可以用,此时的cad界面都已经关闭了...涉及内存释放的问题
//Editor ed = Application.DocumentManager.MdiActiveDocument.Editor; RunIAutoGo("Terminate");
} // 通过反射获取所有继承了IAutoGo接口的类!
// https://www.cnblogs.com/yelanggu/p/5196156.html
// 然后反射实例化,运行它!
// https://www.cnblogs.com/yanshanshuo/p/3905621.html void RunIAutoGo(string methodName = "Initialize")
{
const string iAutoGo = "IAutoGo";
var typeList = new List<RunClass>(); //储存
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())//当前的应用程序域,也就是acad或者gcad的域
{
foreach (Type getTypes in assembly.GetTypes())//获取类型集合
{
foreach (Type getInterfaces in getTypes.GetInterfaces())//获取接口集合
{
if (getInterfaces != null &&
!string.IsNullOrEmpty(getInterfaces.Name) &&
getInterfaces.Name == iAutoGo)//找到接口的函数
{
//再找里面的Initialize
foreach (MemberInfo member in getTypes.GetMembers())//获得它的成员(函数 方法)的信息集合
{
if (member != null && !string.IsNullOrEmpty(member.Name))
{
if (member.Name == methodName)
{
string namePace = Assembly.GetExecutingAssembly().ToString(); //命名空间
string className = member.ReflectedType.FullName; //类名
typeList.Add(new RunClass(namePace, className));
break;
}
}
}
}
}
}
} //按照 SequenceId 排序
typeList = typeList.OrderBy(runClass => runClass.SequenceId).ToList(); var sb = new StringBuilder();
int num = ;
foreach (var item in typeList)
{
try
{
item.Run(methodName);
}
catch (System.Exception e)
{
num++;
sb.Append("错误");
sb.Append(num.ToString());
sb.Append("\n\r");
sb.Append("探索接口RunIAutoGo出错,错误NamePace:\n\r");
sb.Append(item.NamePace);
sb.Append("\n\r错误ClassName:\n\r");
sb.Append(item.ClassName);
sb.Append("\n\r错误信息:\n\r");
sb.Append(e.Message);
sb.Append("\n\r\n\r");
}
}
if (sb.Length > )
{
MessageBox.Show(sb.ToString(), "惊惊连盒");
}
}
}
封存上面的,之后也不用动了....
任何需要实现启动运行的函数,都去实现 : IAutoGo
注意一下
public class Test : IAutoGo
{
public Sequence SequenceId()
{
//最好只使用一次,用于初始化工具集的路径之类的优先项
return Sequence.First; //其余均使用last
//return Sequence.Last;
} public void Initialize()
{ Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;//命令栏交互
ed.WriteMessage("惊惊博客是 https://www.cnblogs.com/JJBox/ ");
} public void Terminate()
{ }
}
cad.net IExtensionApplication接口的妙用 分开写"启动运行"函数的更多相关文章
- flask 中使用蓝图将路由分开写在不同文件
flask 若想将不同的路由写在不同的文件中(如将 user 对象的相关接口写在一个文件中,将 customer 对象的相关接口写在另一个文件中),可以使用蓝图来实现. 有关蓝图的定义:A Bluep ...
- background低版本安卓浏览器不支持复合属性,要分开写
background:url("http://..../xxx.jpg") no-repeat center/cover; 这种复合形式在有些低端安卓浏览器中不支持,最好分开写: ...
- C#深度学习の接口传参(interface)-----接口的妙用
一.接口可以干嘛 我们知道,接口的本质是一个约束规范,委托是方法纵向(形式上)的封装,接口是不同方法横向(广度)的封装 接口中不能有变量,但是可以有属性方法.常见的,我们可以用接口: 1.实现需求方的 ...
- 易宝支付Demo,生产中封装成简洁的代付接口,不用request如何获取项目运行时的真实路径
最近项目在做融360引流,涉及到了易宝支付的代扣和代付.易宝官方给出的demo只能简单运行,而且都是通过form表单的形式提交,返回XML格式.同时接口代码都写在了JSP中看起来不友好.项目在生成中想 ...
- 记录python接口自动化测试--把测试结果写进excel文件(第九目)
python中一般使用xlrd(excel read)来读取Excel文件,使用xlwt(excel write)来生成Excel文件(可以控制Excel中单元格的格式),需要注意的是,用xlrd读取 ...
- ItcastOA_设计BaseDao_设计DAO接口和实现类_写DAO实现类中的方法内容
3. 基础功能 3.1. 设计BaseDao接口与BaseDaoImpl类 每个实体都应有一个对应的Dao,他封装了对这个实体的数据库操作.例 实体Dao接口实现类 ================= ...
- 快速开发框架(FDMS)新增1000个对外接口都不须要手写一行代码
一个大型系统难免会跟其它系统有数据交换,这里就要提供数据接口给外部系统. 曾经在一家智能终端设备的公司上班.那段时间的主要工作就是写接口.接口须要与手机.手持设备.系统管理软件等进行数据交换.总结了一 ...
- require js 将config和入口函数分开写
原文地址 https://github.com/jrburke/requirejs/issues/354 Area there any plans to standardize/recommend a ...
- 为什么C++中声明和定义要分开写
现在开始写项目了,你会发现我们一般都要写一个cpp,对应的还得有一个h文件,那么为什么在C++中我们要这么做? .h就是声明,.cpp就是实现,而所谓分离式实现就是指"声明"和&q ...
随机推荐
- c# asp.net core取当月第一天和最后一天及删除最后一个字符的多种方法
当月第一天0时0分0秒 DateTime.Now.AddDays( - DateTime.Now.Day).Date 当月最后一天23时59分59秒 DateTime.Now.AddDays( - D ...
- WPF样式与触发器(3)
WPF中的各类控件元素, 都可以自由的设置其样式. 诸如: 字体(FontFamily) 字体大小(FontSize) 背景颜色(Background) 字体颜色(Foreground) 边距(Mar ...
- English--音标拼读
English|音标拼读 音标拼读主要内容是,如何使用音标进行单词的拼读,并且会有相应的语音现象,最关键的还是自己多加练习,多听~ 前言 目前所有的文章思想格式都是:知识+情感. 知识:对于所有的知识 ...
- 微信小程序页面调用自定义组件内的事件
微信小程序页面调用自定义组件内的事件 page page.json { "usingComponents": { "my-component": ". ...
- i春秋——“百度杯”CTF比赛 十月场——GetFlag(md5碰撞、文件包含、网站绝对路径)
需要提交的captcha满足等式,肯定就是MD5碰撞了 附上脚本 import hashlib def func(md5_val): for x in range(1,100000000): md5_ ...
- APS中生产计划排程模块的基本原理
高级计划系统(APS)作为ERP和MES的补充,用于协调物流.开发瓶颈资源和保证交货日期. APS包括需求和供应计划.运输和生产计划排程等各种供应链计划模块,本文主要介绍APS中生产计划排程模块的基本 ...
- 第一篇 Scrum 冲刺博客
一.各个成员在 Alpha 阶段认领的任务 姓名 Alpha 阶段认领的任务 林剑峰 用户信息页面:完成用户信息的上传 石竞贤 发布信息页面:完成用户图片上传云存储的功能,并且把发布信息上传到云数据库 ...
- JavaScript 作用域不完全指北
什么是作用域 对于几乎所有编程语言,最基本的功能之一就是能够存储变量的值,并且能在之后对这个值进行访问和修改.这样就会带来几个问题,这些变量存储在哪里?程序在需要的时候又是如何找到它们的?要解决这些问 ...
- 解决Mac下SourceTree每次都让输入密码的问题
在Mac上操作sourcetree当pull和push时每次都是让输入密码,非常烦人,虽然大概知道是因为SSH什么的问题,但搜索百度也没发现解决办法. 于是乎搜索谷歌,发现如下解决办法. Source ...
- 1. Ubuntu下使用pip方式安装tensorflow
参考文档: https://tensorflow.google.cn/install/pip 首先明确,我们采用python3环境. 1. 先确认本机已安装好python3的环境 python3 -- ...