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 ...
随机推荐
- $.fn.extend 与 $.extend的区别
今天看到别人写的jquery 代码都是这样的 $.fn.extend 所以查询了一下,因为自己不是前端开发,看到这样写的,感觉很牛逼.从百度上搜到的感觉解释的还是挺好的,作为记录,方便以后查找. 搜索 ...
- webpack打包js文件
当输入 webpack 输入指令 npm run dev 后会自动启动一个浏览器 需要借鉴插件 open-browser-webpack-plugin 下载:npm install open-bro ...
- SAP云平台和第三方CRM解决方案(火锅)互联
光看封面配图,这篇文章很容易被误认为在讲成都的美食之一:火锅. SAP成都研究院坐落在被联合国教科文组织授予过"美食之都"称号的成都,所在的天府软件园,半径1公里左右星罗棋布着很多 ...
- 普通Java项目中使用Sl4j+Log4j2打印日志
因工作需要,采用JavaFx开发了一个windows窗口程序.在开发过程中,由于没有引入日志框架,只能自己手动在控制台打印些信息,给调试带来了很多麻烦:因此决定引入日志框架.由于之前接触的项目 ...
- Codeforces H. Kilani and the Game(多源BFS)
题目描述: Kilani and the Game time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- CentOS6.10部署的Tomcat8.5启动后,浏览器访问不到的解决方法
解决过程如下: 一.关闭 selinux 和 iptables 防火墙 二.查看 tomcat 是否在运行 ps aux |grep tomcat 三.查看端口情况 lsof -i:8080 查看后都 ...
- 转: 【前端福利】用grunt搭建自动化的web前端开发环境-完整教程
http://blog.csdn.net/wangfupeng1988/article/details/46418203
- oracle在windows(含客户端工具pl/sql安装)下安装
安装Oracle服务器端 系统默认创建的数据库名称为orcl,可自行修改. 全局数据库名(用来唯一标示Oracle数据库,每个数据库至少由一个Oracle系统标识符(SID)引用),orcl,后面称为 ...
- STM32片上Flash容量大小命名规则
- VIJOS-P1320 清点人数
JDOJ 1427: VIJOS-P1320 清点人数 题目传送门 Description 初始时,火车上没有学生:当同学们开始上火车时,年级主任从第一节车厢出发走到最后一节车厢,每节车厢随时都有可能 ...