熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

Autodesk官方最新的.NET教程(三)(C#版)

2013-11-13 10:03:28  來源: .NET編程 

   章 數據庫基礎: 創建我們自己的Employee 對象 
   
  打開Lab文件夾下的Lab工程文件或或接著Lab的代碼 
   
  在這一章中我們將創建一個Employee 對象(包括一個圓一個橢圓和一個多行文本對象)這個對象屬於一個自定義的EmployeeBlock塊(這個塊駐留在EmployeeLayer當在模型空間插入這個塊的時候EmployeeLayer層就會擁有這個塊的一個塊索引)本章的每一個步驟中的代碼都可以運行這樣做的目的可以使你更清楚地知道每一部分代碼完成的功能第一步將簡要說明一下如何在模型空間創建一個圓 
   

  

  這一章的重點是在AutoCAD中訪問數據庫的基礎主要內容包括事務處理(Transaction)對象Id(ObjectId)符號表(symbol tables如塊表BlockTable和層表LayerTable)以及對象引用使用的其它一些對象如顏色Color三維點Pointd和三維向量Vectord都和各自的步驟有關但重點應該放在數據庫基礎上 
   
  ) 創建一個名為CREATE的命令它調用函數CreateEmployee()這個函數用來在模型空間(MODELSPACE)的()點處創建一個半徑為的圓
  
  [CommandMethod(test)]
  
  public void createCircle()
  
  {
  
  
  
  //首先聲明我們要使用的對象
  
  Circle circle; //這個是我們要加入到模型空間的圓
  
  BlockTableRecord btr;//要加入圓我們必須打開模型空間
  
  BlockTable bt; //要打開模型空間我們必須通過塊表(BlockTable)來訪問它
  
  
  
  //我們使用一個名為Transaction的對象把函數中有關數據庫的操作封裝起來
  
  Transaction trans;
  
  
  
  //使用TransactionManager的StartTransaction()成員來開始事務處理
  
  trans = HostApplicationServicesWorkingDatabaseTransactionManagerStartTransaction();
  
  
  
  //現在創建圓……請仔細看這些參數——注意創建Pointd對象的New和Vectord的靜態成員ZAxis
  
  circle = new Circle(new Pointd( ) VectordZAxis );
  
  bt = (BlockTable)transGetObject(HostApplicationServicesWorkingDatabaseBlockTableId OpenModeForRead);
  
  
  
  //使用當前的空間Id來獲取塊表記錄——注意我們是打開它用來寫入
  
  btr = (BlockTableRecord)transGetObject(HostApplicationServicesWorkingDatabaseCurrentSpaceIdOpenModeForWrite );
  
  
  
  //現在使用btr對象來加入圓
  
  btrAppendEntity(circle);
  
  transAddNewlyCreatedDBObject(circle true); //並確定事務處理知道要加入圓!
  
  
  
  //一旦完成以上操作我們就提交事務處理這樣以上所做的改變就被保存了……
  
  transCommit();
  
  
  
  //…然後銷毀事務處理因為我們已經完成了相關的操作(事務處理不是數據庫駐留對象可以銷毀)
  
  transDispose();
  
  
  
  } 
       
   
  請仔細閱讀一下上面的代碼塊的結構可以通過注釋來了解相關的細節 
   
  注意要編譯代碼你必須導入AutodeskAutoCADDatabaseServices 和AutodeskAutoCADGeometry命名空間 
   
  運行這個函數來看看它是否可行應該會在圖形中創建一個在()處的半徑為的白色的圓 
   
   
   
  ) 我們可以減少代碼的輸入量這可以通過聲明一個Database變量代替HostApplicationServicesWorkingDatabase來實現
  
   Database db = HostApplicationServicesWorkingDatabase; 
   
   
   
  使用這個變量來代替在代碼中出現的HostApplicationServicesWorkingDatabase 
   
  ) 在上面的代碼中我們沒有使用任何異常處理而異常處理對一個正確的NET應用程序來說是非常重要的我們要養成使用異常處理的好習慣所以讓我們在這個函數中加入trycatchfinally 
   
  ) 為了使代碼緊湊我們可以把許多變量的聲明和初始化放在同一個語句中現在你的代碼看起來應該是這樣的   
   
   [CommandMethod(CREATE)]
  
  public void CREATEEMPLOYEE()
  
  {
  
  
  
  Database db = HostApplicationServicesWorkingDatabase;
  
  Transaction trans = dbTransactionManagerStartTransaction();
  
   try
  
   {
  
  Circle circle = new Circle(new Pointd( ) VectordZAxis );
  
  BlockTable bt = (BlockTable)transGetObject(dbBlockTableId OpenModeForRead);
  
  BlockTableRecord btr = (BlockTableRecord)transGetObject(HostApplicationServicesWorkingDatabaseCurrentSpaceIdOpenModeForWrite);
  
  btrAppendEntity(circle);
  
  transAddNewlyCreatedDBObject(circle true);
  
  transCommit();
  
   }   
   
   
   catch
  
   {
  
  edWriteMessage(Error );
  
   }
  
  finally
  
  {
  
  transDispose();
  
  }
  
  }
  
  End Function 
   
  運行你的代碼來進行測試…… 
   
  上面的catch塊只顯示一個錯誤信息實際的清理工作是在finally塊中進行的這樣做的理由是如果在事務處理被提交(Commit())之前Dispose()被調用的話事務處理會被 銷毀我們認為如果在transCommit()之前出現任何錯誤的話你應該銷毀事務處理(因為Commit將永遠不會被調用)如果在Dispose()之前調用了Commit()也就是說沒有任何錯誤發生那麼事務處理將會被提交給數據庫 
   
  所以基於上面的分析Catch塊其實並不是必須的因為它只用來通知用戶程序出現了一個錯誤它將在下面的代碼中被去掉 
   
  ) 現在讓我們在Employee加入剩下的部分橢圓和多行文本的實例
  
    多行文本實體
  
    中心點應該與圓心的創建一樣
  
    (建議創建一個名為center而值為的Pointd變量來表示中心點)
  
    多行文本的內容可以是你的名字
  
    橢圓(提示你可以先看一下Ellipse的構造函數)
  
    法向量應該沿著Z軸(請查看Vectord類型)
  
    主軸設為Vectord()(提示不要忘了用new)
  
    半徑比例設為
  
    橢圓還必須閉合(也就是說開始和結束點必須相同) 
   
  運行你的代碼來進行測試……應該可以生成一個圓一個橢圓和一個中心點在的多行文本 
   
  注意和事務處理對象有關的NET API中的TryCatchFinally塊結構應該是異常觀察者實際上我們是在try塊中實例化對象的但沒有顯式地銷毀它們當產生異常的時候可能會產生問題特別是當觀察者注意到我們實際上用的是封裝的非托管對象!記住當資源不再使用的時候垃圾收集機制就會回收內存垃圾收集機制會不時的調用封裝類的Dispose()方法刪除非托管對象 
   
  這裡還要注意的是Dispose()作用於封裝的非托管類對象的方式取決於對象是否是數據庫駐留對象由非數據庫駐留對象調用的Dispose()會刪除非托管對象而由數據庫駐留對象調用的Dispose()只是關閉它們
  <![if !supportLineBreakNewLine]>
  <![endif]
   
  ) 接下來讓我們來創建一個新的函數它用來新建一個顏色為黃色名字為EmployeeLayer 的AutoCAD層 
   
  這個函數應該檢查是否這個層已經存在但不管這個層是否存在函數都應該返回EmployeeLayer的ObjectId下面是這個函數的代碼
  
  public ObjectId CreateLayer()
  
  {
  
  ObjectId layerId; //它返回函數的值
  
  Database db = HostApplicationServicesWorkingDatabase;
  
  Transaction trans = dbTransactionManagerStartTransaction();
  
  //首先取得層表……
  
  LayerTable lt = (LayerTable)transGetObject(dbLayerTableId OpenModeForWrite);
  
  //檢查EmployeeLayer層是否存在……
  
  if (ltHas(EmployeeLayer))
  
  {
  
   layerId = lt[EmployeeLayer];
  
  }
  
  else
  
  {
  
  //如果EmployeeLayer層不存在就創建它
  
  LayerTableRecord ltr = new LayerTableRecord();
  
  ltrName = EmployeeLayer; //設置層的名字
  
  ltrColor = ColorFromColorIndex(ColorMethodByAci );
  
  layerId = ltAdd(ltr);
  
  transAddNewlyCreatedDBObject(ltr true);
  
  }
  
  
  
  transCommit();
  
  transDispose();
  
  return layerId;
  
  } 
   
   
   
  是不是覺得這個函數的基本結構與在模型空間加入實體的代碼比較類似?訪問數據庫的方法都是這樣的使用事務處理來獲取數據庫對象在符號表(模型空間所在的塊表也是符號表之一)中加入實體然後讓事務處理知道 
   
  ) 在這個函數中加入異常處理就像在CreateEmployee函數中的一樣 
   
  ) 接下來改變新建層的顏色下面是實現的代碼片斷請把它加入到你的代碼中
  
  ltrColor = ColorFromColorIndex(ColorMethodByAci
   
   
   
  注意ColorMethodByAci可以讓我們使用AutoCAD ACI顏色索引……這裡為(表示黃色)
  
   <![if !supportLists]>) <![endif]>回到CreateEmployee()函數加入把上面創建的幾個實體設置到EmployeeLayer層的代碼聲明一個類型為ObjectId的變量用CreateLayer函數的返回值給它賦值使用每個實體(文本圓和橢圓)的LayerId屬性設置它們所在的層 
   
   
   
  例如 textLayerId = empId 
   
   
   
  運行代碼來查看EmployeeLayer層是否已被創建所有已創建的實體是否都在這一層上(應該顯示為黃色) 
   
  ) 現在為各個實體設置不同的顏色可以使用ColorIndex屬性(ColorIndex屬性表示AutoCAD的顏色)
  
   圓為紅色-
  
   橢圓為綠色-
  
   文本為黃色- 
   
   
   
  運行代碼看看實體的顏色是否為設置的值即使這些實體是在EmployeeLayer層上 
   
  ) 接下來我們要在AutoCAD數據庫中創建一個獨立的塊然後把它插入到塊表而不是模型空間中 
   
  首先把CreateEmployee函數的名字改為CreateEmployeeDefinition() 
   
  加入以下代碼來創建一個獨立的塊   
   
  BlockTableRecord newBtr = new BlockTableRecord();
  
  newBtrName = EmployeeBlock;
  
  newBtrId = btAdd(newBtr);
  
  transAddNewlyCreatedDBObject(newBtr true);   
   
   
  ) 現在請稍微改動一下加入實體到模型空間的代碼(改為加入塊到塊表中記得加入前要打開塊表) 
   
  現在運行代碼然後使用INSERT命令來檢查是否可以正確插入這個塊 
   
   
   
  ) 最後我們要創建一個位於模型空間的塊索引它表示上面創建的塊的一個實例這一步留給大家練習 
   
  下面是你要遵循的最基本的步驟
  
   <![if !supportLists]>A) <![endif]>創建一個名為CreateEmployee新的函數
  
   <![if !supportLists]>B) <![endif]>把命令屬性CREATE移動到CreateEmployee()
  
   <![if !supportLists]>C) <![endif]>修改CreateEmployeeDefintion()來返回新創建的塊EmployeeBlock的ObjectId操作的步驟請參考CreateLayer()的作法
  
   <![if !supportLists]>D) <![endif]>你需要修改CreateEmployeeDefintion()來查看塊表中是否已包含EmployeeBlock如果包含這個塊則返回它的ObjectId(做法與CreateLayer()一樣) 
   
  提示bt的聲明語句移動到try塊的頂部使用BlockTableHas()方法把其它的代碼移動到else語句
  
  try
  
   {
  
   //獲取BlockTable 對象
  
  BlockTable bt = (BlockTable)transGetObject(dbBlockTableId OpenModeForWrite);
  
   if ((btHas(EmployeeBlock)))
  
   {
  
   newBtrId =bt[EmployeeBlock];
  
   }
  
   else
  
   {
  
   …
  
  
  
   <![if !supportLists]>E) <![endif]>在新創建的CreateEmployee()函數中創建一個新的BlockReference對象並把它加入到模型空間提示我們可以使用CreateEmployeeDefinition()中引用模型空間的代碼這些代碼在這裡不需要了
  
   <![if !supportLists]>F) <![endif]>在CreateEmployee中調用CreateEmployeeDefinition()函數使上面生成的BlockReference對象的BlockTableRecord()指向CreateEmployeeDefinition()函數提示請參考BlockReference的構造函數 
  


From:http://tw.wingwit.com/Article/program/net/201311/12425.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.