在托管程序中使用事务处理
和ObjectARX程序一样,托管程序总是在数据库事务处理环境下对DWG数据库执行操作。你应当使用下述的异常处理技巧:
使用带异常处理的事务处理
1. 通过调用Transaction.StartTransaction()方法,在try块之前启动一个事务处理
2. 在try块内,使用事务处理对象来进行和数据库有关的操作。
3. 通过调用Transaction.Commit()方法,在try块的末尾提交事务处理。
4. 通过调用Transaction.Dispose()方法在finally块中销毁事务处理。
上述步骤保证事务处理对象被销毁, 而不管在try块中可能出现的任何异常。下面的例子描述了这一技巧:
//C#
public static void HyperCommand(){ Database db = Application.DocumentManager.MdiActiveDocument.Database; DBTransMan tm = db.TransactionManager; //开始一个事务处理 Transaction myT = tm.StartTransaction(); Try
{ //创建一条直线 Line line=new Line(New Point3d(0, 0, 0), New Point3d(1, 1, 0)); BlockTable bt = CType(tm.GetObject(_ db.BlockTableId, OpenMode.ForRead, False), BlockTable); BlockTableRecord btr = CType(tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False), BlockTableRecord); '把直线加入到model space block table record btr.AppendEntity(line); '确定事务处理知道这个新加入的对象 tm.AddNewlyCreatedDBObject(line, true); '添加一些超链接 HyperLink hyper=new HyperLink(); hyper.Name = "www.autodesk.com"; line.Hyperlinks.Add(hyper); If(line.Hyperlinks.Contains(hyper)) hyper.Name = "www.gotdotnet.com"; line.Hyperlinks.Add(hyper) int i; for(i =0; i < line.Hyperlinks.Count; i ++) Debug.WriteLine(line.Hyperlinks(i).ToString()); //提交事务处理 myT.Commit(); } finally { myT.Dispose(); } } 'VB.NET Public Shared Sub HyperCommand() Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database Dim tm As DBTransMan = db.TransactionManager 'start a transaction Dim myT As Transaction = tm.StartTransaction() Try 'create a line Dim line As New Line(New Point3d(0, 0, 0), New Point3d(_ 1, 1, 0)) Dim bt As BlockTable = CType(tm.GetObject(_ db.BlockTableId, OpenMode.ForRead, False), BlockTable) Dim btr As BlockTableRecord = CType(tm.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite, False), BlockTableRecord) 'add it to the model space block table record btr.AppendEntity(line) 'make sure that the transaction knows about this new object tm.AddNewlyCreatedDBObject(line, True) 'add some hyperlinks Dim hyper As New HyperLink() hyper.Name = "www.autodesk.com" line.Hyperlinks.Add(hyper) If line.Hyperlinks.Contains(hyper) Then hyper.Name = "www.gotdotnet.com" End If line.Hyperlinks.Add(hyper) Dim i As Integer For i = 0 To line.Hyperlinks.Count - 1 Debug.WriteLine(line.Hyperlinks(i).ToString()) Next i 'commit transaction myT.Commit() Finally myT.Dispose() End Try End Sub 'HyperCommand
使用ResultBuffer类
在ObjectARX中,resbuf结构给AutoCAD专门数据提供了一个灵活的存储器。在托管API中,这个结构被映射在Autodesk.AutoCAD.DatabaseServices.ResultBuffer类中。
一个ResultBuffer类对象使用的方法与resbuf数据链相同。你要定义一个ResultBuffer并使它产生一系列的数据对。每一对数据由一个数据类型描述和一个值组成。在托管API中,这些数据对是Autodesk.AutoCAD.DatabaseServices.TypedValue类的实例。这个类实现的功能与resbuf结构的restype和resval成员一样。
TypedValue.TypeCode属性是一个16位的整数值,它表示TypedValue.Value属性的数据类型。可以使用的TypeCode值取决于ResultBuffer实例的具体使用情况。例如,适合于xrecord定义的TypeCode的值就不一定适用于xdata。Autodesk.AutoCAD.DatabaseServices.DxfCode枚举定义的代码精确地描述了所有可能的ResultBuffer数据类型的范围。
因为TypedValue.Value属性与System.Object的一个实例相对应,所以它可以包含任何数据类型。但是,Value数据必须与TypeCode所表示的类一致,以保证结果的可用性。
你可以通过给ResultBuffer的构造函数传递一个TypedValue对象数组来提前产生一个ResultBuffer,或者可以先构造一个空的ResultBuffer,然后通过调用ResultBuffer::Add()方法来加入新的TypedValue对象。一个典型的ResultBuffer构造函数的用法如下例所示:
//C#
Xrecord rec=new Xrecord();
rec.Data = New ResultBuffer( _ New TypedValue(CInt(DxfCode.Text), "This is a test"), _ New TypedValue(CInt(DxfCode.Int8), 0), _ New TypedValue(CInt(DxfCode.Int16), 1), _ New TypedValue(CInt(DxfCode.Int32), 2), _ New TypedValue(CInt(DxfCode.HardPointerId), db.BlockTableId), _ New TypedValue(CInt(DxfCode.BinaryChunk), New Byte(){0, 1, 2, 3, 4}), _ New TypedValue(CInt(DxfCode.ArbitraryHandle), db.BlockTableId.Handle), _ New TypedValue(CInt(DxfCode.UcsOrg), New Point3d(0, 0, 0)));
'VB.NET
Dim rec As New Xrecord() rec.Data = New ResultBuffer( _ New TypedValue(CInt(DxfCode.Text), "This is a test"), _ New TypedValue(CInt(DxfCode.Int8), 0), _ New TypedValue(CInt(DxfCode.Int16), 1), _ New TypedValue(CInt(DxfCode.Int32), 2), _ New TypedValue(CInt(DxfCode.HardPointerId), db.BlockTableId), _ New TypedValue(CInt(DxfCode.BinaryChunk), New Byte(){0, 1, 2, 3, 4}), _ New TypedValue(CInt(DxfCode.ArbitraryHandle), db.BlockTableId.Handle), _ New TypedValue(CInt(DxfCode.UcsOrg), New Point3d(0, 0, 0)))
托管程序的初始化和运行时优化
托管程序如果要执行初始化或结束任务,那么可以通过实现可选的Autodesk.AutoCAD.Runtime.IextensionApplication接口来进行。这个接口提供Initialize()和Terminate()方法。因为托管程序不能手动卸载,Terminate()方法只有当AutoCAD运行的时候才能调用。
如果程序中定义了大量的类,那么你可以通过实现IextensionApplication接口和使用两个可选的通用属性来优化程序。这两个属性是:ExtensionApplication和CommandClass,它们可以帮助AutoCAD找到程序的初始化路径和命令处理器。
任何托管程序都可以使用这两个属性。但是,只有在大型程序中才能体现它们的优化效果。
|