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 ...
随机推荐
- Python基础12
jupyter notebook 快捷键 ”Ctrl + / ” 快速注释/撤销注释.注释整行或者整段代码.
- laravel框架之即时更改
表单//@foreach($res as $k=>$v) <tr id="{{$v->id}}" > <td>{{$v->id}}< ...
- 如何构思你的iOS App应用
转自:http://mobile.51cto.com/hot-311134.htm 在twitter上,听到不少人问,我也有App 在App Store上面卖,为什么我的App卖得这么少啊?于是我就上 ...
- using 中写 return 一样会释放using 中对象 但是会在外面定义一个一样的对象 赋值后 释放 最后 return 外面定义的那个对象
static DataTable getDataTable() { ")) { SqlCommand com = new SqlCommand("", con); Sql ...
- 0x02 Python logging模块利用配置加载logger
目录 logging模块利用配置加载logger 方式一模板:logging.config.dictConfig(config_dict) logging模块利用配置加载logger logging. ...
- 【Linux】yum 安装 JDK
一.查看java的所有版本 yum list java* 二.安装jdk8 yum install java--openjdk.x86_64 三.检查是否安装完成 java -version 四.默认 ...
- HTTP中分块编码(Transfer-Encoding: chunked)
转自: 妙音天女--分块传输编码~ 参考链接: HTTP MDN--HTTP协议 一.背景: 持续连接的问题:对于非持续连接,浏览器可以通过连接是否关闭来界定请求或响应实体的边界:而对于持续连接,这种 ...
- Cutting Bamboos(2019年牛客多校第九场H题+二分+主席树)
题目链接 传送门 题意 有\(n\)棵竹子,然后有\(q\)次操作,每次操作给你\(l,r,x,y\),表示对\([l,r]\)区间的竹子砍\(y\)次,每次砍伐的长度和相等(自己定砍伐的高度\(le ...
- docker学习10-注册docker hub账号
前言 Docker Hub是Docker的远程镜像仓库,是 docker 官网推出的 docker 仓库的一个公共服务器,在上面可以有私有和公有的镜像. 类似于 github,可以上传自己镜像文件,也 ...
- uboot向kernel的传参机制——bootm与tags
http://blog.csdn.net/skyflying2012/article/details/35787971 最近阅读代码学习了uboot boot kernel的过程以及uboot如何传参 ...