您好,欢迎来到意榕旅游网。
搜索
您的当前位置:首页用_NET进行AutoCAD二次开发的方案探索

用_NET进行AutoCAD二次开发的方案探索

来源:意榕旅游网
用.NET进行AutoCAD二次开发的方案探索 余兴胜技术应用、研究

用.NET进行AutoCAD二次开发的方案探索

余兴胜

(铁道第四勘察设计院桥梁处 武汉430063)

[摘 要] 铁四院正在开发桥梁勘察软件,该软件构建于.NET平台。在运用AutoCAD绘图时,我们对Au2toCAD的各种二次开发工具进行比较研究,决定采用.NET开发托管ARX程序完成绘图功能。虽然托管ARX作为一种新方法还有一些不太成熟的地方,但经过AutoCAD2004、2005到目前2006版的发展,它的功

能已经非常接近于采用C++开发的ARX程序。并且作为一种潮流,它将会是Autodesk公司发展的重点。针对主应用程序和内置于AutoCAD的托管ARX程序属于不同应用程序域的问题,我们又对Windows中跨应用程序域的进程间通讯问题进行研究,实践出一套运用.NET进行AutoCAD二次开发的模式:采用.NET开发托管ARX程序完成绘图;利用ActiveX外部控制AutoCAD并加载托管ARX程序;基于.NETRemoting远程处理技术,采用代理机制通过Http信道在不同应用程序域间传递对象的引用,实现跨应用程序域的进程间通讯。本文针对该模式进行简单描述,对其中一些关键技术作详细说明,并提供相关的C#实现代码。

[关键词] AutoCAD 二次开发 .NETActiveXObjectARX 进程间通讯 Remoting  铁四院是一家面向铁路行业的国有大型勘察设计企业,承担着我国近三分之一的铁路勘设任务。在当前铁路跨越式发展的历史时期,为减少铁路建设对当地人民生活的影响,铁路大多采用高架方式,新建铁路中桥梁所占比重非常大,桥梁勘设任务极为繁重。为缩短桥梁勘察周期,铁四院正在进行桥梁勘察软件的开发,该系统构建于VisualStudio.net平台,主要面向桥梁专业外业

AutoCAD是Autodesk公司的拳头产品,广

1 了解AutoCAD二次开发的各种工具

泛应用于建筑、机械、交通、电力等需要绘图的各种工程领域。它是一个开放架构的通用绘图系统,使你可以根据意愿进行定制和功能扩展。它提供了多种二次开发的工具,下面就当前主要的工具介绍如下:

(1)脚本文件:脚本文件是类似于批处理的ASCII文件。它是AutoCAD命令的集合。加载

勘察工作,用于对桥梁勘察资料进行集中采集和处理,为铁四院桥梁专业外业勘察工作者提供一个一站式的设计平台。主要功能包括水文计算(流量、水位、冲刷等)及桥梁、涵洞、公跨铁的计算

后AutoCAD将一条一条地执行你的命令,你将看到命令行在刷刷地不停滚动,,效率非常低。目前用这种方法开发的系统已不多见。

(2)DXF:DXF是AutoCAD与外部数据交换的标准格式,它用标签的形式表示AutoCAD图形文件中的所有信息。每个数据元素都以一个整型的组码标签开始。组码表示它后面所跟数据元素的类型。DXF也是一个ASCII文件。它要求开发者对DXF文件格式非常熟悉,但要记住那么多无意义的标签可不是一件有意思的事情。

(3)AutoLISP和VisualLISP:AutoLISP是一种功能全面的解释性编程语言,可以用于调用AutoCAD命令、系统变量和对话框。它是由Lisp

39

与绘图等。虽然我们基于GDI+自行开发了一个图形绘制的组件,可以于AutoCAD进行图形处理,但是考虑到要与兄弟专业及设计阶段软件的接口,仍然需要在AutoCAD中绘图。在对AutoCAD二次开发的各种工具进行分析比较后,

根据项目特点,我们考虑采用全托管代码进行AutoCAD的二次开发,并对此进行专门研究和实

践,找到了一套切实可行的方案,下面向大家作个简单的介绍,希望能够起到抛砖引玉的效果。

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

                     铁道勘测与设计                     

语言发展而来,以前作为AutoCAD的定制标准是AutoCAD的一部分,但作为一种过时的技术将逐渐被VisualLISP替代。VisualLISP借助ActiveXAutomation与对象交互,可以对事件作

ObjectARX类名的前四个字母就可以确定对应

托管类的命名空间,如:AcDb与Autodesk.Auto2CAD.DatabaseServices对应。

(7)AutodeskRealDWG:AutodeskRealD2WG提供了100%的DWG文件直接读写功能。

出反应,提供了一个集成的开发环境。它和Au2toLISP一样内置于AutoCAD,可以直接执行Au2toCAD的内部命令,功能强大,但是用它开发大型

它使C++和.NET开发者能够自由读写DWG和DXF文件。对AutoCAD的各个版本具有很好的兼容性。Autodesk公司内部就是使用Re2alDWG来对非AutoCAD的产品提供DWG支持

程序就显得力不从心了。

(4)ActiveXAutomation:通过它你可以从任

何应用程序中访问和控制AutoCAD对象。它可以在AutoCAD的内部或外部运行,通过Com实现进程间通信,可以和其他的Windows程序共享数据。它可以用任何支持ActiveX的语言进行开发,并且可以在外部完全控制AutoCAD,控制它的启动和关闭,加载其他开发工具开发的Auto2CAD内置程序,在速度要求不是很高的情况下,的,例如AutodeskVIZ,AutodeskRevit和Au2todeskInventor。链接RealDWG类库的服务程

序可以在AutoCAD程序没有运行的情况下直接读写DWG文件。它提供定制对象的框架,支持内存文件操作。不幸的是他是一个收费技术,对于单个程序的初始许可费用就是$5,000,以后每年还要缴年费$2,500,需要开发多个程序的每个还要再增加$2,500。看清楚数字前面的dollar符号,这样高的价格可并非我们这样的小系统所能承担得了的。

应当成为首选。

(5)ObjectARX:即AutoCAD运行时扩展编程环境,包含C++库。这些库是一些构造块,可用来开发AutoCAD应用程序、扩展AutoCAD类和协议以及创建新命令,新命令的操作与Au2toCAD内置命令的操作方式相同。它通过直接

2 用C#开发托管ARX程序

通过以上对各种方法的分析和比较,根据自己项目的特点,我们决定采用C#开发托管Ob2jectARX程序。虽然目前它作为一种新方法还有

操作AutoCAD的数据库、图形系统和内部命令等来定制和扩展AutoCAD,无论从功能上还是运行速度上都是最好的。但是它只能采用C++来开发,对C++不很熟悉的开发人员来说可不是个好东东。

(6)托管ObjectARX:通过AutoCAD的托管ObjectARX可以使用.NET所支持的任何语言进

一些不太成熟的地方,但经过2004、2005到目前的2006版的发展,它的功能已经很接近采用C++的ObjectARX。并且作为一种潮流,它将会是Autodesk公司发展的重点。这对于我们这些不

行开发,达到和用C++开发的ObjectARX几乎同样强大的功能。托管ObjectARX封装了绝大部分的ObjectARXSDK,它可以执行数据库功能,使你可以读写DWG文件,访问AutoCAD的界面元素,包括命令行、特性对话框、编辑器、发布和出图工具等。它由acdbmgd.dll和acbmgd.dll两个程序集组成。acdbmgd.dll是ObjectDBXSDK的一部分,内部封装了ObjectDBXAPI,ac2mgd.dll封装了大部分AutoCADAPI。托管Ob2jectARX和绝大部分ObjectARX类对应,通过40

熟悉C++,又想获得强大功能,又不想多掏银子的开发者来说可真是个好东东。好了,选定了绘图的方法,说干就干,翻阅帮助我们很快就开发出了绘制桥涵图形的托管ARX程序的框架,使用netload加载,一切顺利,但目前它只是个架子,什

么工作也不做。接下来我们使用了ActiveXAu2tomation,用它来控制AutoCAD的启动和关闭,

加载我们的托管ARX程序框架。AutoCADAc2tiveX将AutoCAD对象显示到“外部世界”,一旦

这些对象被显示,许多不同的编程语言和环境就

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

             余兴胜:用.NET进行AutoCAD二次开发的方案探索          

可以访问它们。它能够使用户从AutoCAD的内部或外部以编程方式来操作AutoCAD。在我们的项目同样采用C#。

要使用AutoCADActiveX,我们首先必须添加AutoCAD2006TypeLibrary的引用。当然根据您的CAD版本的不同,类型库的名称也会不同。在我们的程序中是通过创建类GetAutoCAD来实现对AutoCAD的控制。当创建该类的实例时它的构造函数就会试图用(AcadApplication)(AutoCAD.Applica2Marshal.GetActiveObject“

)来获得当前正在运行的AutoCAD,如果tion.16”

   (\"netload\"你的托管ARX程序);

  恢复对话框

  application.ActiveDocument.SetVariable(\"File2Dia\",1);

}

我们的托管ARX程序加载以后,绘图的工作就由ARX程序来完成了。托管ObjectARX通过一个特殊的类来实现装载时的初始化工作。这个类只要实现IExtensionApplication接口,并暴露一个组件级别的属性(此属性把类定义为Exten2sionApplication)就可以了。我们创建这样的类LoadInitialize如下:

[assembly:ExtensionApplication(typeof(LoadInitial2ize))]

publicclassLoadInitialize:IExtensionApplication{

获取失败(可能是没有正在运行的AutoCAD)就用newAcadApplicationClass()创建一个。这个类的构造函数如下:

publicGetAutoCAD()} try {  //创建实例时谋略获得已运行的AutoCAD  应用程度对象,若出错则创建新对象  _application=(AcadApplication)Marshal.

  GetActiveObject(\"AutoCAD.Application.16\");  _application.Visible=true;  }  catch  {   try   {    //创建AutoCAD应用程序对象   _application=newAcadApplicationClass=();    _application.Visible=true;    _initialired=true;   }   catch   {throw;}  }

}在程序中需要调用AutoCAD的地方调用下

要响应一次性的装载和卸载事件必须实现接口IExtensionApplication的Initialize()和Ter2minate()函数,分别完成装载时的初始化工作和

卸载时的清理工作。

publicvoidInitialize(){  //这里是你想在加载托管ARX程序之后  //要做的事情,我们的项目中在这里  //加载自定义的菜单、工具条,面板  等,然后运行绘图。}

publicvoidTerminate(){  //此处作一些垃圾回收工作,  //注意托管ARX程序垃圾回收  //的特点。}

3 用Remoting实现托管ARX

程序与主程序间的通讯

好了,现在绘图的机制已经建立了,就等于架好了炉灶等米下锅了。可是米———绘制内容从哪里来呢?我们的主应用程序和AutoCAD属于两个不同的应用程序域。托管ARX程序内置于AutoCAD,位于AutoCAD的应用程序域。托管ARX程序如何访问主应用程序中的绘制对象呢?

面的函数(使用时注意添加异常处理部分代码),创建类GetAutoCAD的实例就可以获得Auto2CAD的Handle,加载我们的托管ARX程序了。

publicvoidLoadARX()

{

  GetAutoCADconnector=newGetAutoCAD();  application=connector.Application;  //设置系统变量禁止对话框出现

  application.ActiveDocument.SetVariable(\"Fild2Dia\",0);

  //加载你的你的托管ARX程序,注意空格符  application.ActiveDocument.SendCommand

这属于跨应用程序域的进程间通讯范畴,在开始之前我们有必要先来了解下Windows中的进程和进程间通信。

41

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

                     铁道勘测与设计                     

用户提交给计算机的任务最终都是通过一个个的进程来完成的。在一组并发进程中的任何两个进程之间,如果都不存在公共变量,则称该组进程为不相交的。在不相交的进程组中,每个进程都于其它进程,它的运行环境与顺序程序一样,而且它的运行环境也不为别的进程所改变。运行的结果是确定的,不会发生与时间相关的错误。Windows中实现进程间通信的方法很多,本机上可以还通过广播消息、匿名管道、COM技术、内存映射、临界区等,网络间的可以通过命名管道、套接字、远程过程调用(RPC)、Webservices和.NET中提供的方法。鉴于主程序和绘图机制都建立在.net环境下,因此我们首选了.NET中提供的方法。

.NETFramework提供了几种与不同应用程通信协议替换另一种通信协议,或者用一种序列化格式替换另一种序列化格式,而不必重新编译客户端或服务器。此外,远程处理系统假定没有特别的应用程序模型。可以从Web应用程序、控制台应用程序、Windows服务,即差不多可以从希望使用的任何程序中进行通信。远程处理服务器也可以是任何类型的应用程序域。任何应用程序都可以承载远程处理对象并向其计算机或网络上的任何客户端提供服务。使用在IIS中承载的基于HTTP的应用程序。.NETRemoting将会获得所需的可缩放性,可以使用IIS所提供的安全服务。但当在IIS之外承载时,它不会提供任何安全服务,你必须提供所需的安全功能。SOAP编码的性能通常低于二进制编码,在使用HTTP连接时您也可以使用二进制编码替代SOAP编码格式来提高速度。但当您需要在不同的操作系统之间交互操作时,则通常使用SOAP格式化协议。

使用.NETRemoting可以:通过引用传递对象并返回到特定应用程序域中的特定对象。直接控制激活特性和对象生存期。实现和使用第三方信道或协议来扩展通信以满足特定要求。直接参与通信进程以创建所需的功能。若要使用.NETRemoting生成让两个组件在其中跨越应用程序

序域中的对象进行通信的方式,每一种方式都具有特定级别的专业性和灵活性。ASP.NET和.NETRemoting都是进程间的通信实现方法。ASP.NET提供一种由Internet信息服务(IIS)

承载的基础结构,该结构擅长处理基本类型,而且是Web应用程序开发人员所熟悉的。.NETRe2moting是具有一般性和可扩展性的进程间通信系

统,可以用来创建在IIS中承载的XMLWebservices(它具有ASP.NET和IIS的所有安全

性、可伸缩性以及会话和应用程序状态),或者用来创建使用其他任何类型的通信协议或序列化格式的应用程序。由于我们的项目并不需要在WEB上部署,所以我们选择了.NETRemoting。

.NETRemoting使您能够方便地构建大范

域边界直接通信的应用程序,只需生成以下对象:

●可远程处理的对象。

●侦听对该对象的请求的宿主应用程序域。●对该对象发出请求的客户端应用程序域。即使在复杂的多客户端/多服务器应用程序中,仍可以认为.NETRemoting具有这一特性。宿主和客户端应用程序也必须用远程处理基础结构来进行配置。

远程处理系统创建一个表示该类的代理对象,并向客户端返回一个对该代理对象的引用。当客户端调用方法时,远程处理基础结构将处理调用,检查类型信息,并通过信道将该调用发送到服务器进程。侦听信道获得该请求并将其转发给服务器远程处理系统,服务器远程处理系统查找(或在必要时创建)并调用被请求的对象。然后,此过程将

围分布式应用程序,而不管应用程序组件是全部集中在一台计算机上还是分布在世界各地。您可以生成这样的客户端应用程序:它们使用同一台计算机(或可通过网络达到的其他任何计算机)上的其他进程中的对象。您也可以使用.NETRe2moting与同一进程中的其他应用程序域进行通

信。.NETRemoting为进程间通信提供了一种抽象的方法,它将可远程处理的对象与特定客户端或服务器应用程序域以及特定的通信机制隔离开来。因此,这很灵活且容易自定义。可以用一种42

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

             余兴胜:用.NET进行AutoCAD二次开发的方案探索          

反向进行,服务器远程处理系统将响应捆绑成消息并由服务器信道发送到客户端信道。最后,客户端远程处理系统通过代理将调用的结果返回给客户端对象。客户端通过URL来定位服务器中的远程处理对象,远程处理系统模型见图1。‘

系统,使它可以使用信道来侦听对类型的请求。.NETFramework包括两个默认的信道:Ht2tpChannel(它使用SOAP格式化)和TcpChannel(它使用二进制格式化)。最好使用HttpChannel

信道,因为在某些方案中可以通过防火墙使用该信道而不必打开端口,而且该信道支持标准的安全和身份验证协议。由于远程配置是基于每个应用程序域进行的,因此应用程序域必须处于运行状态才能侦听请求。下面是我们的宿主程序域中的一个函数,由于我们的绘图对象是宿主程序域中的当前对象(可能是新建或既有线的桥梁、涵洞和公跨铁中的一种,它们都从BaseItem基类继承,都是可发布远程处理对象),所以我们要在主程序中根据当前对象的改变动态发布绘图对象。

图1中的信道是一个承载数据流,根据特定网络协议创建包并将该包发送到另一台计算机的类型。某些信道只能接收信息,另外一些只能发送信息,还有一些可以在两个方向上使用,例如默认的TcpChannel和HttpChannel类。

以上所述都是我们下面工作的基础。现在开始切入正题,生成使用.NETRemoting跨应用程序域边界进行通信的应用程序的过程并不复杂。您必须实现可远程处理的类型、侦听或宿主应用程序域、客户端或调用应用程序域,并且必须配置每个应用程序域中的远程处理系统,以便将远程激活用于可远程处理的类型。无论远程处理方案有多复杂,这一过程都会适用。

首先我们要创建一个可远程处理的对象,若要使其他应用程序域中的对象使用类的实例,该类必须从MarshalByRefObject继承。在我们的项目中我们的远程处理对象是新建及既有线桥梁、涵洞和公跨铁对象,这些对象都是从BaseItem这个基类继承而来,所以我们就让BaseItem基类从MarshalByRefObject继承即可。

接下来若要使其他应用程序域中的对象能够在远程创建该对象的实例,必须生成宿主或侦听器应用程序,以完成以下两项任务:选择并注册一个信道,该信道是为您处理网络协议和序列化格式的对象。将您的类型注册到.NETRemoting

具体做法是设置一个DrawObject属性,当该属性改变时调用下面这个函数。由它来动态发布绘图对象。

privatevoidSetObjToDraw(objectitem)

{  //如果绘图对象没有改变就不用重新发布

  if(item!=null&&!item.Equals(this.dra2wObject))

  {   try   {    if(chan!=null)//检测信道是否已被注册    {     if(this.drawObject!=null)     {  //取消前远程处理对象的发布    RemotingServices.Unmarshal(objRef);    RemotingServices.Disconnect

   (System.MarshalByRefObject)drawObject);    }   }   else   {    //注册信道    chen=newHttpChannel(8099);    ChannelServices.RegisterChannel(chan);   }   this.drawObject=item;   //动态发布对象   objRef=RemotingServices.Marshal    ((System.MarshalByRefObject)item    \"DrawObject\",item.GetType());   }   catch(System.Exceptione)   {    Console.WriteLine(e.Message);    if(item!=null)

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

43

                     铁道勘测与设计                           RemotingServices.Disconnect)item);      ((System.MarshalByRefObject)item);    if(item!=null)    {   ChannelServices.UnregisterChannel(chan);      chan=null;     }    }   }  }

时我们使用了发布对象的GetType()方法,它得到的是对象的真正类型而非BaseItem类型。在客户端我们注册的是BaseItem,要想获得真正的对象还需要做一次类型转换。如果你不小心将动态发布类型设置为BaseItem,这是个极隐蔽的错误,就因为这个问题折腾了我两天。因为在客户端是通过代理来访问远程对象的,代理是根据发布类型创建的,因此你在客户端将只知道BaseItem类型,你将无法访问除BaseItem类型以

以上我们在主程序中建立了宿主应用程序,定义并发布了我们的远程处理类型,现在我们要在AutoCAD应用程序域中托管ARX程序中建立该远程类型的客户端。为此,托管ARX程序必须将其自身注册为该远程对象的客户端,然后就像该对象位于客户端的应用程序域中一样调用它。.NETRemoting系统将截获客户端调用,将其转发到远程对象,并将结果返回到客户端。由于宿主程序中采用的是动态发布,所以在需要调用远程对象的地方我们都要调用下面这个函数来获得远程对象代理,以保证获得主程序中最新发布的绘图对象。

  publicGetAutoCAD ()  {   try   {    //创建实例时谋略获得已运行的AutoCAD    //应用程序对象,若出错则创建新对象    _application=(AcadApplication)Marshal.  GetActiveObject(\"AutoCAD.Application.16\");   }   catch   {    try    {     //创建AutoCAD应用程序对象   _application=newAcadApplicationClass();     _application.Visible=true;     _initialized=true;    }    catch    {throw;}  }}

外的对象成员。

事情到了这里似乎已经很完美了,如果你跟着我的介绍做的话,你将会看到你的工作运行得很好,速度也非常快,估计会和我一样准备给自己的同事做演示。呀!怎么了,刚刚还好好的,咋就跳出找不到远程对象的错误了呢?关闭主程序和AutCAD,重新再来,一切又OK了,可等了一会

又出现同样的错误,这是怎么回事呢?仔细翻阅Remoting的帮助,原来是远程对象的生存期问

题,引用封送对象无论是服务器激活的Singleton对象还是客户端激活的对象,都不会永远驻留在内存中。相反,除非该类型重写MarshalByRe2fObject类的InitializeLifetimeService方法控制自

己的生存期策略,否则每个该对象的生存期都由租约、租约管理器和一些主办方的组合来控制。关于生存期及租约的详细资料请查看帮助。在我们的项目中仅需要远程对象永远不过期,解决的办法就比较简单了,在基类中重载MarshalByRe2fObject类的方法InitializeLifetimeService让它返

回null就行了。

publicoverrideobjectInitializeLifetimeService()

{

  returnnull;}

最后还有一点要注意,如果你的远程对象包含有其他的自定义对象,你想在客户端通过远程对象的引用来访问这些对象可就有些困难了。虽然根据Remoting的帮助所述,这样似乎是可以的,但目前我还没有找到这方面的例子,而且经过我的多次实验也没有成功,搞不清楚问题出在哪里。没办法我们只好另辟蹊径,曲径通幽了,当客户端访问这些自定义对象时,宿主程序将这些对

4 需要注意的几个问题

在这里要注意了,我们在建立宿主程序中发布的对象都是BaseItem的子类,在动态发布类型44

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

             余兴胜:用.NET进行AutoCAD二次开发的方案探索          

象序列化到内存中,并以字节数组的形式传递给客户端,客户端再将字节数组变为内存流并最终重构该对象。我们通过SaveToByte和GetObj2FromByte两个函数来实现,只需将YourObj替换

附件:文章中所用源代码

publicGetAutoCAD()

{ try {  //创建实例时试图获得已运行的AutoCAD  //应用程序对象,若出错则创建新对象  _application=(AcadApplication)Marshal.

(AutoCAD.Application.   GetActiveObject“

);16”

  _application.Visible=true; } catch {  try  {   //创建AutoCAD应用程序对象   _application=newAcadApplicationClass();   _application.Visible=true;   _initialized=true;  }  catch  {throw;} }}

publicvoidLoadARX(){

  GetAutoCADconnector=newGetAutoCAD();

为你的对象类型就可以了,注意客户端要有对该对象类型的引用,使用时需要添加异常处理代码。

//将对象序列化到内存流中存储到字节数组publicbyte[]SaveToByte(){

  XmlSerializermySerializer=new   XmlSerializer(typeof(YourObj);

  MemoryStreammyStream=newMemoryStream();

  mySerializer.Serialize(myStream,this);

  myStream.Seek(0,0);  byte[]buffer=newbyte[myStream,Length];

  myStream.Read(buffer,0,buffer,Length);  myStream,Close();  returnbuffer;}

//从字节数组中重构对象

publicYourObjGetObjFromByte(byte[]buffer){

  XmiSerializermySerializer=

   newXmiSerializer(typeof(YourObj));

  MemoryStreammyStream=newMemoryStream(buffer);

YourObj obj=

   (YourObj)mySerializer.Deserialize(myS2tream);

  myStream.Close(); returnobj;}

.NETRemoting在默认情况下不进行身份

验证或加密。因此,建议您在与客户端或服务器进行远程交互之前,采取任何必要的措施确认它们的身份。因为,NETRemoting应用程序需要FullTrust权限才能执行,所以未经授权的客户端

如果被授予了访问您的服务器的权限,该客户端就可能像完全受信任的客户端一样执行代码。应始终验证终结点的身份并将通信流加密,通过在Internet信息服务(IIS)中承载远程类型,或者通过生成自定义通道接收对来完成这项工作。具体实现请读者参阅相关资料自己完善吧,限于篇幅就介绍到这里了,希望对您能有所帮助。

  application=connector.Application;  //设置系统变量禁止对话框出现

(File2  application.ActiveDocument.SetVariable“

Dia”,0);

  //加载你的你的托管ARX程序,注意空格符  application.ActiveDocument.SendCommand

(netload你的托管ARX程序”);   “  //恢复对话框

(File2  application.ActiveDocument.SetVariable“

Dia”,1);

}

[assembly:ExtensionApplication(typeof(LoadInitial2ize))]

publicclassLoadInitialize:IExtensionApplication  publicvoidInitialize()  {   //这里是你想在加载托管ARX程序之后   //要做的事情,我们的项目中在这里   //加载自定义的菜单、工具条,面板   //等,然后运行绘图。}

publicvoidTerminate(){

   //此处作一些垃圾回收工作,   //注意托管ARX程序垃圾回收   //的特点。}

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

45

                     铁道勘测与设计                     

privatevoidSetObjToDraw(objectitem){//如果绘图对象没有改变就不用重新发布

  if(item!=null&&!item.Equals(this.dra2wObject))

  {   try   {    if(chan!=null)//检测信道是否已被注册    {     if(this.drawObject!=null)     {//取消前远程处理对象的发布

      RemotingServices.Unmarshal(ob2jRef);

      RemotingServices.Disconnect

      ((System.MarshalByRefObject)dra2wObject);

     }   }   else   {    //注册信道    chan=newHttpChannel(8099);    ChannelServices.RegisterChannel(chan);   }   this.drawObject=item;   //动态发布对象   objRef=RemotingServices.Marshal    ((System.MarshalByRefObject)item    “,DrawObject”,item.GetType());  }  catch(System.Exceptione)  {   Console.WriteLine(e.Message);   if(item!=null)

    RemotingServices.Disconnect

     ((System.MarshalByRefObject)item);    if(chan!=null)    {

     ChannelServices.UnregisterChannel(chan);

     chan=null;    }   }  } }

privatevoidGetDrawObject(){  try  {   if(channel==null)   {    channel=newHttpChannel();    ChannelServices.RegisterChannel(channel);    //注册远程对象,第二个参数是远程对象的URI

    RemotingConfiguration.RegisterWell2KnownClientType

(BaseItem”)     (Type.GetType“

);     ,“http://localhost:8099/DrawObject”

  }  //并非实际创建对象,它获得的是远程对象的引

  BaseItemitem=newBaseItem();  drawObject=item;  //此处是为对激活的远程对象进行试用,   //如果有错则可抛出异常,进入异常处理   ed.WriteMessage(item.Name);}

catch(System.Exceptione){  ed.WriteMessage(e.Message);  //显示一个对话框询问用户指定远程对象服务器

  //或是直接加载对象文件  if(询问对话框==DialogResult.OK)  {   //连接远程服务器对象或直接加载对象文件  }  else   return; }}

publicoverrideobjectInitializeLifetimeService(){

  returnnull;}

//将对象序列化到内存流中存储到字节数组publicbyte[]SaveToByte(){

  XmlSerializermySerializer=new   XmlSerializer(typeof(YourObj));

  MemoryStreammyStream=newMemoryStream

();

  mySerializer.Serialize(myStream,this);  myStream.Seek(0,0);

  byte[]buffer=newbyte[myStream.Length];  myStream.Read(buffer,0,buffer.Length);  myStream.Close(); returnbuffer;}

//从字节数组中重构对象

publicYourObjGetObjFromByte(byte[]buffer){

  XmlSerializermySerializer=

   newXmlSerializer(typeof(YourObj));

  MemoryStreammyStream=newMemoryStream(buffer);

  YourObjobj=

   (YourObj)mySerializer.Deserialize(myS2tream);

  myStream.Close();  returnobj;}

收稿日期:2006-3-6

46

铁道勘测与设计 RAILWAYSURVEYANDDESIGN2006(3)

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务