国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

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

2019-11-18 19:18:07
字體:
來源:轉載
供稿:網友

第 4 章  數據庫基礎2:  添加自定義數據

在這一章中,我們將創建一個新的字典對象,它用來表示我們雇員就職的 ‘Acme 公司‘(呵呵,當然是虛構的一家公司)的部門。這個“部門”字典對象將包含一個表示部門經理的記錄。我們還會加入代碼到雇員創建過程,這個過程會加入一個索引到雇員工作的部門。

我們要說明的是如何在DWG文件中創建自定義數據,包括“每個圖形”的自定義數據和“每個實體”的自定義數據。“每個圖形”的自定義數據是指只在整個圖形中加入一次的數據,它表示對象可以引用的單一類型或特性。“每個實體”的自定義數據是指是為特定的對象或數據庫中的實體加入的數據。

在下面的示例中,我們將加入“每個圖形”的自定義數據到命名對象字典(簡稱NOD)。NOD存在于每一個DWG文件中。“每個實體”的自定義數據加入到一個名為“擴展字典”的字典(可選)中,它表示每一個雇員。每一個由DBObject派生的對象都擁有存儲自定義數據的擴展字典。而在我們的示例中將包含這種自定義數據如名字、薪水和部門。

因此這一章的重點是字典對象和擴展記錄(XRecord),它們是我們用來表示自定義數據的容器。

首先讓我們來創建表示公司的條目。在本章的前幾個步驟中,我們將創建如下所示的部門層次結構:

  NOD-命名對象字典

     ACME_DIVISION-自定義公司字典

               銷售(Sales) -部門字典

                       部門經理-部門條目

 

請打開Lab4文件夾下的Lab4工程,或接著Lab3的代碼。

<!--[if !supportLists]-->1)                   <!--[endif]-->我們首先要做的是定義一個新的函數,它用來在命名對象字典(NOD)中創建公司字典對象。為這個函數取名為CreateDivision(),,并使用命令屬性來定義CREATEDIVISION命令。

下面是這個函數的代碼,它的形式非常簡單,只是用來在NOD中創建一個ACME_DIVISION(用來表示公司)

 [CommandMethod("CreateDivision")]

 public void CreateDivision()

 {

       Database db = HostapplicationServices.WorkingDatabase;

       Transaction trans = db.TransactionManager.StartTransaction();

 

       try

       {

              //首先,獲取NOD……

              DBDictionary NOD = (DBDictionary)trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForWrite);

              //定義一個公司級別的字典

              DBDictionary acmeDict;

              try

              {

                     //如果ACME_DIVISION不存在,則轉到catch塊,這里什么也不做

                     acmeDict = (DBDictionary)trans.GetObject(NOD.GetAt("ACME_DIVISION"), OpenMode.ForRead);

              }

              catch

              {

                     //如果ACME_DIVISION不存在,則創建它并把它加入到NOD中……

                     acmeDict = new DBDictionary();

                     NOD.SetAt("ACME_DIVISION", acmeDict);

                     trans.AddNewlyCreatedDBObject(acmeDict, true);

              }

              trans.Commit();

       }

       finally

       {

              trans.Dispose();

       }

}

 

請仔細閱讀一下上面的代碼塊的結構,可以通過注釋來了解相關的細節。特別要注意的是我們是如何用一個try-catch塊來處理ACME_DIVISION是否存在?如果ACME_DIVISION字典不存在,GetObject()將會拋出異常,catch塊被執行,它會創建一個新的字典。

運行這個函數來看它是否可行。可以使用數據庫查看工具來檢查字典是否已被加入(建議使用ARX SDK的ArxDbg工具)

<!--[if !supportLists]-->2)                   <!--[endif]-->接下來,我們要在ACME_DIVISION字典中加入銷售(Sales)條目。銷售(Sales)條目同樣也是一個字典。由于銷售(Sales)字典與ACME_DIVISION字典的關系如同ACME_DIVISION字典與NOD,所以代碼是類似的。定義下面的代碼部分在ACME_DIVISION字典中創建一個名為’Sales’的字典。

代碼提示:

 

                   DBDictionary divDict;

                   try

       {

              divDict = (DBDictionary)trans.GetObject(acmeDict.GetAt("Sales"), OpenMode.ForWrite);

       }

       catch

          …

 

運行函數來看‘Sales’條目是否已加入到ACME_DIVISION字典。

<!--[if !supportLists]-->3)                   <!--[endif]-->現在我們要在這個字典中加入一個特殊的記錄,它可以包含任意的自定義數據。我們要加入的數據類型為擴展記錄(XRecord),它可以包含任何東西,因此我們可以讓它包含ResultBuffer類的對象(就是有些人可能非常熟悉的‘resbuf’)。ResultBuffer可以存儲不同類型的預定義數據。擴展記錄存儲任意數目的ResultBuffer關系列表,因此可能會很大。下表是可以包含在ResultBuffer中一些數據類型(位于Database類的DxfCode枚舉中):

 

Start

0

 

Text

1

 

XRefPath

1

 

ShapeName

2

 

BlockName

2

 

AttributeTag

2

 

SymbolTableName

2

 

MstyleName

2

 

SymTableRecName

2

 

AttributePRompt

3

 

DimStyleName

3

 

LinetypeProse

3

 

TextFontFile

3

 

 

在下面的代碼部分,我們將創建只包含一個ResultBuffer的擴展記錄。這個ResultBuffer包含一個單一的的字符串值,它表示’Sales’部門的部門經理的名字。我們使用和加入字典一樣的方法加入擴展記錄。唯一的區別是擴展記錄與字典的不同:

             mgrXRec = new Xrecord();

  mgrXRec.Data = new ResultBuffer(new TypedValue((int)DxfCode.Text, "Randolph P. Brokwell"));

 

請看一下我們是怎樣使用new來創建一個新的擴展記錄。但我們也使用了new來創建一個ResultBuffer,傳入的參數是一個名為‘TypedValue’的對象。‘TypedValue’對象和C++中resbuf的成員‘restype’是類似的。這個對象一般表示一個特定類型的DXF值,我們使用它來組裝諸如擴展數據或擴展記錄之類的通用數據容器。在這里,我們簡單地使用DxfCode.Text鍵值和“Randolph P. Brokwell”數據值來定義一個TypedValue,然后把它作為單一的參數傳入ResultBuffer構造函數(由new來調用)中。

XRecord的’Data’屬性實際上正是擴展記錄鏈的第一個ResultBuffer,我們使用它來表示擴展記錄鏈是從什么地方開始的。

所以接下來的代碼塊看起來和前面兩個非常相似:

Xrecord mgrXRec;

              try

              {

                     mgrXRec = (Xrecord)trans.GetObject(divDict.GetAt("Department Manager"), OpenMode.ForWrite);

              }

              catch

              {

                     mgrXRec = new Xrecord();

                     mgrXRec.Data = new ResultBuffer(new TypedValue((int)DxfCode.Text, "Randolph P. Brokwell"));

                     divDict.SetAt("Department Manager", mgrXRec);

                     trans.AddNewlyCreatedDBObject(mgrXRec, true);

              }

 

運行函數并使用數據庫查看工具來確定部門經理已被加入到’Sales’字典。

 

4)    我們已經定義了公司字典,現在我們要把每個雇員的數據加入到前一章定義的塊索引中。我們要加入的數據是:名字、薪水和雇員所屬的部門。要加入這些數據,我們要同前幾個步驟一樣使用擴展記錄。因為我們要加入三個條目,所以我們要使擴展記錄可以把這些數據聯系在一起。

一般來說,擴展記錄只能存在于字典中。而我們要為每個雇員加入這些數據(就是本章開頭所講的“每個圖形”的自定義數據和“每個實體”的自定義數據),那應該怎么做呢?答案就是:每一個對象或AutoCAD中的實體實際上都有一個名為’擴展字典(Extension Dictionary)’的可選字典。我們可以把擴展記錄直接加入到這個字典中。

請回到我們在上一章創建的CreateEmployee()函數。這個函數是我們創建塊索引的地方。

讓我們像前面的步驟一樣來創建一個新的擴展記錄。因為我們要加入3個條目,因此我們既可以使用ResultBuffer的Add方法(它會在擴展記錄鏈中加入一個鏈接),也可以利用ResultBuffer的構造函數(它的一種構造函數可以輸入可變數量的參數)。

無論用哪一種方法,請在CreateEmployee()函數中使用ResultBuffer來創建一個新的XRecord,ResultBuffer包括以下的類型和值:

       Text – “Earnest Shackleton”        (或是你選擇的其它雇員的名字)

       Real – 72000                或者更多的薪水J

       Text – “Sales”               雇員所在的部門

      

5)    要把上面的擴展記錄加入到塊索引,我們必須把它加入到擴展字典。通常這個字典是不存在的,除非它被明確地創建,塊索引就是這種情況。要給一個對象創建擴展字典,你要調用它的成員‘CreateExtensionDictionary()’。這個函數不返回任何值,所以要訪問它創建的擴展字典,你還得使用對象的‘ExtensionDictionary’屬性。你可以使用類似于以下的代碼來創建并訪問擴展字典:

 

       br.CreateExtensionDictionary();

       DBDictionary brExtDict  = (DBDictionary)trans.GetObject(br.ExtensionDictionary, OpenMode.ForWrite, false);

 

由于擴展字典也是字典,我們可以和第3步一樣在擴展字典中加入擴展記錄。請完成有關的代碼來創建和訪問塊索引的擴展字典,加入你在第4步中創建的擴展記錄,然后把擴展記錄加入到事務處理。

6)    返回到NOD……因為在NOD中創建公司字典只需要一次(就像創建Employee塊一樣),因此我們應該把CreateDivision函數的命令屬性去掉,而在CreateEmployeeDefinition()中調用這個函數。請自己完成這些改變。當所有這些都做完后,當CREATE命令第一次運行的時候,所有的函數都會被調用。

7)    下面的步驟和上面的無關。我們將創建一個函數來遍歷模型空間,以用來查找加入的Employee對象(這里其實是塊索引)的數目。在VB.NET 或C#中,我們可以把模型空間塊表記錄(ModelSpace BlockTableRecord)當作一個集合,這樣就可以使用For Each(C#是foreach)來遍歷它。請仔細研究一下下面的代碼片斷:

 

VB.NET:

            Dim id As ObjectId ‘  首先,定義一個For循環要使用的ObjectId變量。

            For Each id In btr

                Dim ent As Entity = trans.GetObject(id, OpenMode.ForRead, False) '打開當前的對象!

 

C#:

       foreach (ObjectId id in btr)

       {

            Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead, false);  //打開當前的對象!

 

一旦我們獲得模型空間對象,你們就可以定義一個ObjectId變量,然后把它用于For Each循環(C#是foreach)。

現在,我們需要使用一些方法來篩選雇員。我們知道模型空間中的對象都是實體,但不全是雇員。我們需要使用一些方法來加以區分。在這里,我們可以使用VB.NET的TypeOf關鍵字并用CType進行類型轉換(C#是GetType函數和typeof):

VB.NET:

                If TypeOf ent Is BlockReference Then

              Dim br As BlockReference = CType(ent, BlockReference)

              …

 

C#:

       If(ent.GetType() == typeof(BlockReference))

              BlockReference br = (BlockReference)ent;

 

上面講的概念對于AutoCAD編程是很重要的,因為容器對象經常包含不同類型的對象。你會在AutoCAD程序的開發中經常碰到這種類型轉化。

請定義一個名為EmployeeCount()的函數,函數的結構如上所示,它用來統計模型空間中的塊索引的數目。這個函數不會輸出任何東西,但你可以使用逐步調試程序來查看整數變量的增加(每發現一個塊索引對象)。

8)  接下來,為了把結果輸出到命令行,我們需要使用Application.DocumentManager.MdiActiveDocument.Editor對象的服務。要使用它,請加入下面的代碼:

 

Imports Autodesk.AutoCAD.EditorInput

Imports Autodesk.AutoCAD.ApplicationServices

 

在函數的內部:

Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;


最后,在循環的后面確定找到了多少個塊索引:

ed.WriteMessage("Employees Found: " + nEmployeeCount.ToString());

 

第四章結束

下面的代碼片斷演示了怎樣獲取Employee對象的所有內容,包括ACME_DIVISION字典中的部門經理的名字。這部分要在后面的章節中使用,但因為它和本章有關,因此我們把它放在本章作介紹。如果有時間的話,請閱讀一下其中的代碼來看看它是怎么使用的。它可以被直接放到你的類中并可以運行。命令的名字是PRINTOUTEMPLOYEE。ListEmployee()函數接收一個ObjectId參數,它通過一個ref類型的字符串數組返回值(包含相應的雇員數據)。調用它的PrintoutEmployee()函數只是用來在命令行中輸出這些數據。

我們需要一個遍歷并顯示所有雇員數據的命令。

public static void ListEmployee(ObjectId employeeId, ref string[] saEmployeeList)

{

       int nEmployeeDataCount = 0;

       Database db = HostApplicationServices.WorkingDatabase;

       Transaction trans = db.TransactionManager.StartTransaction(); //開始事務處理。

       try

       {

              Entity ent = (Entity)trans.GetObject(employeeId, OpenMode.ForRead, false); //打開當前對象!

              if (ent.GetType() == typeof(BlockReference))

              {

//不是所有的塊索引都有雇員數據,所以我們要處理錯誤

                     bool bHasOurDict = true;

                     Xrecord EmployeeXRec = null;

                     try

                     {

                            BlockReference br = (BlockReference)ent;

                            DBDictionary extDict = (DBDictionary)trans.GetObject(br.ExtensionDictionary, OpenMode.ForRead, false);

                            EmployeeXRec = (Xrecord)trans.GetObject(extDict.GetAt("EmployeeData"), OpenMode.ForRead, false);

                     }

                     catch

                     {

bHasOurDict = false; //出現了錯誤……字典或擴展記錄不能訪問

                     }

 

if (bHasOurDict) //如果獲得擴展字典,而又有擴展記錄……

                     {

 

                            // 為雇員列表分配內存

                            saEmployeeList = new String[4];

                            //加入雇員的名字

                            TypedValue resBuf = EmployeeXRec.Data.AsArray()[0];

                            saEmployeeList.SetValue(string.Format("{0}/n", resBuf.Value), nEmployeeDataCount);

                            nEmployeeDataCount += 1;

                            //加入雇員的薪水

                            resBuf = EmployeeXRec.Data.AsArray()[1];

                            saEmployeeList.SetValue(string.Format("{0}/n", resBuf.Value), nEmployeeDataCount);

                            nEmployeeDataCount += 1;

                            //加入雇員所在的部門

                            resBuf = EmployeeXRec.Data.AsArray()[2];

                            string str = (string)resBuf.Value;

                            saEmployeeList.SetValue(string.Format("{0}/n", resBuf.Value), nEmployeeDataCount);

                            nEmployeeDataCount += 1;

                            //現在,讓我們從公司字典中獲取老板的名字

                            //在NOD中找到.

                            DBDictionary NOD = (DBDictionary)trans.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead, false);

                                          DBDictionary acmeDict = (DBDictionary)trans.GetObject(NOD.GetAt("ACME_DIVISION"), OpenMode.ForRead);

                            //注意我們直接使用擴展數據...

                                          DBDictionary salesDict = (DBDictionary)trans.GetObject(acmeDict.GetAt((string)EmployeeXRec.Data.AsArray()[2].Value), OpenMode.ForRead);

                            Xrecord salesXRec = (Xrecord)trans.GetObject(salesDict.GetAt("Department Manager"), OpenMode.ForRead);

                            //最后,把雇員的數據輸出到命令行

                            resBuf = salesXRec.Data.AsArray()[0];

                            saEmployeeList.SetValue(string.Format("{0}/n", resBuf.Value), nEmployeeDataCount);

                            nEmployeeDataCount += 1;

                     }

              }

              trans.Commit();

       }

       finally

       {

              trans.Dispose();

       }

}

 

      

[CommandMethod("PRINTOUTEMPLOYEE")]

public static  void PrintoutEmployee()

{

       Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

       //聲明我們將在下面使用的工具...

       Database db = HostApplicationServices.WorkingDatabase;

       Transaction trans = db.TransactionManager.StartTransaction();

       try

       {

              //首先,獲取塊表和模型空間塊表記錄

BlockTable bt = (BlockTable)trans.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead);

              BlockTableRecord btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead);

              //現在,我們需要把內容輸出到命令行。這里可以有一個對象幫助我們:

                      //下面的部分,我們將遍歷模型空間:

 

              foreach (ObjectId id in btr)

              {

                     Entity ent = (Entity)trans.GetObject(id, OpenMode.ForRead, false); //打開當前對象!

                     if (ent is BlockReference)

                     {

                            string[] saEmployeeList = null;// 這是正確的...定義新的列表。

                           

                            ListEmployee(id, ref saEmployeeList);

                            if ((saEmployeeList.Length == 4))

                            {

                                   ed.WriteMessage("Employee Name: {0}", saEmployeeList[0]);

                                   ed.WriteMessage("Employee Salary: {0}", saEmployeeList[1]);

                                   ed.WriteMessage("Employee Division: {0}", saEmployeeList[2]);

                                   ed.WriteMessage("Division Manager: {0}", saEmployeeList[3]);

                            }

                     }

              }

       }

       finally

       {

       }     

}


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 调兵山市| 方城县| 阜平县| 乌兰察布市| 柳林县| 麦盖提县| 台中市| 榆树市| 房产| 漳平市| 永昌县| 信丰县| 望城县| 武平县| 澜沧| 邢台市| 西畴县| 蒲城县| 商丘市| 石河子市| 德钦县| 葫芦岛市| 武鸣县| 卓尼县| 炉霍县| 吉林省| 禄丰县| 西贡区| 金秀| 乐业县| 中西区| 喜德县| 金沙县| 苍溪县| 九龙县| 舒城县| 军事| 综艺| 乌拉特前旗| 宁晋县| 突泉县|