CorrelationParameter特性_第1頁
CorrelationParameter特性_第2頁
CorrelationParameter特性_第3頁
CorrelationParameter特性_第4頁
CorrelationParameter特性_第5頁
已閱讀5頁,還剩19頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

1、CorrelationParameter特性假如你考慮在單一宿主應(yīng)用程序的環(huán)境下可能會出現(xiàn)多個工作流實例的話,你可能將會發(fā)現(xiàn)傳送數(shù)據(jù)的事件和方法也會傳送某種唯一的標(biāo)識符。一個訂單處理系統(tǒng)可能要傳送一個客戶ID,或者一個包裝系統(tǒng)可能要傳送一個批號。這個唯一標(biāo)識符的類型是確定數(shù)據(jù)唯一實例的完美候選,事實上,的確如此。當(dāng)你在你的通信接口中設(shè)計方法和事件的時候,你也要為其設(shè)計一個數(shù)據(jù)相關(guān)ID的簽名。數(shù)據(jù)相關(guān)ID在所有的空間和時間情況下并不保證必須是唯一的。但是,假如它不是一個Guid,它就必定要保證在工作流實例執(zhí)行期間要被唯一地使用。也許令人驚訝的是,假如你創(chuàng)建了兩個相關(guān)的工作流實例,它們使用了同一個

2、參數(shù)值(即創(chuàng)建了兩個使用了同一客戶ID的工作流)在同一時間運行的話,這并不是一個錯誤。關(guān)聯(lián)僅僅和使用了單一的關(guān)聯(lián)參數(shù)值的單一的工作流實例聯(lián)系起來。使用一個關(guān)聯(lián)參數(shù)值創(chuàng)建的工作流在調(diào)用方法和事件進行數(shù)據(jù)交換時使用了不同的關(guān)聯(lián)值的地方則是錯誤,在這些地方WF可幫助你防止產(chǎn)生錯誤。你要在你的接口定義中包括CorrelationParameter特性來通知WF哪些方法參數(shù)要承載這個數(shù)據(jù)關(guān)聯(lián)ID值(把它們放在ExternalDataExchange特性的旁邊)。當(dāng)數(shù)據(jù)傳遞的時候WF能夠檢查參數(shù)的內(nèi)容。例如,假如你的邏輯試圖混淆客戶或者(包裝)批號的話,WF將拋出System.Workflow.Activ

3、ity.EventDeliveryFailedException。這個異常對你很有幫助,因為它指出了你的處理邏輯部分存在明確的不匹配的數(shù)據(jù)。例如,一個客戶卻為其它客戶買單,顯而易見,這種結(jié)果是不期望發(fā)生的。假如你接收到一個異常,你就需要去檢查你應(yīng)用程序中不正確的邏輯處理操作。CorrelationParameter特性在它的構(gòu)造器中接收一個字符串。這個字符串代表了你的接口所使用的包含了唯一ID的參數(shù)的名稱。假如你要為某一指定的方法進行對該參數(shù)進行重命名,你就可通過使用CorrelationAlias參數(shù)來為這些事件和方法進行參數(shù)的重命名。你將在本章的稍后部分讀到關(guān)于這個參數(shù)的更多知識。Corr

4、elationInitializer特性當(dāng)數(shù)據(jù)通信開始進行的時候,WF也需要初始化相關(guān)令牌。為了方便地完成這個工作,你可在方法或事件上加入CorrelationInitializer特性來進行數(shù)據(jù)通信,這可能有多個事件或方法需要添加這個特性。在執(zhí)行該方法或事件前進行相關(guān)數(shù)據(jù)的來回傳送的任何企圖其結(jié)果都是產(chǎn)生一個異常,并會在這個異常中標(biāo)記該關(guān)聯(lián)初始化器。CorrelationAlias特性當(dāng)你創(chuàng)建相關(guān)的服務(wù)后,CorrelationParameter特性通過名稱來識別出被用來傳送數(shù)據(jù)相關(guān)標(biāo)識符的方法參數(shù)。對于你的接口方法來說,這意味著你必須有一個方法參數(shù)使用了和相關(guān)參數(shù)名相同的名稱來命名。假如你

5、的代理(delegate或稱委托)以相關(guān)參數(shù)定義在代理中的方式創(chuàng)建的話,這沒有任何問題。但是這對于事件來說就不適用了。當(dāng)你使用一個包含了事件參數(shù)的代理并且這些事件參數(shù)要傳送相關(guān)參數(shù)的時候問題出現(xiàn)了。例如,設(shè)想你的相關(guān)參數(shù)被命名為customerID,然后考慮一下下面這個代理:delegatevoidMyEventHandler(objectsender,MyEventArgse);假如使用了這個委托的事件被放進你的通信接口中后,customerID參數(shù)沒有在事件處理程序中出現(xiàn),當(dāng)你執(zhí)行你的工作流的時候,WF會拋出一個異常來指出關(guān)聯(lián)被錯誤地使用。但是,假如MyEventArgs有一個包含了客戶I

6、D的屬性的話,你就能使用CorrelationAlias特性來指出它。對本例子而言,假如MyEventArgs的客戶ID屬性被命名為CustomerID的話,相關(guān)參數(shù)的別名(alias)就將是e.CustomerID。一個重要的事情是要牢記住一旦你為某一單一的工作流實例初始化了一個相關(guān)數(shù)據(jù)路徑的話,你就不能在該工作流實例的生命周期中改變該數(shù)據(jù)的關(guān)聯(lián)ID而不會出現(xiàn)錯誤。例如,一旦你和一個用客戶的ID號作為聯(lián)系的工作流實例通信的話,以后你就不能使用其他客戶的ID號來和同一個工作流實例進行數(shù)據(jù)通信。意思就是,就像把信息插入進一個數(shù)據(jù)表中新行的時候,假如你的處理過程涉及到創(chuàng)建客戶的ID號,你就需要預(yù)先

7、生成該客戶的ID號。你不能讓數(shù)據(jù)庫為你生成它們,或者開始默認(rèn)為“空”(“empty”)然后在后來使用一個新生成的ID號,因為這樣你的通信過程就會在沒有客戶ID的情況下被初始化。提到的這些ID號如果有所不同的話,你的工作流就會拋出一個異常。創(chuàng)建相關(guān)工作流在本章中我介紹了關(guān)聯(lián)的概念并只提到了三個特性。這就是所有的東西嗎?對的。但是我們的本地服務(wù)變得更加復(fù)雜,因為我們必須考慮不同的數(shù)據(jù)流。記住,本地通信服務(wù)在工作流運行時中是一個單例(singleton)服務(wù),因此各個不同的工作流實例所請求的全部數(shù)據(jù)都必須通過這個本地通信服務(wù)。該服務(wù)不可避免地必須知悉各個工作流實例和關(guān)聯(lián)參數(shù)的細(xì)節(jié)以便當(dāng)宿主從一個指定

8、的工作流請求數(shù)據(jù)的時候,該服務(wù)能返回正確的數(shù)據(jù)。備注:你怎樣架構(gòu)你的本地通信服務(wù)取決于你。在本章的稍后部分我將為了展示我是怎么創(chuàng)建它們的,但最終沒有任何規(guī)則要讓你也必須像我所做的一樣去創(chuàng)建你的服務(wù)。唯一的要求是你要能從你的服務(wù)中返回正確的相關(guān)數(shù)據(jù)。為了讓你能理解下面更大的圖片,我將首先介紹你將使用的應(yīng)用程序并解釋它為什么使用關(guān)聯(lián)。相關(guān)工作流的典型例子是一個訂單處理系統(tǒng),它使用唯一的客戶ID號去了解客戶的訂單信息。本章的示例應(yīng)用程序模擬了一個貨運公司可能用來跟蹤其車輛的應(yīng)用程序。今天,許多長途卡車都裝備了全球定位系統(tǒng)(GPS),它能把卡車的位置報告給運輸公司。無論卡車發(fā)生了什么,你都能跟蹤它并監(jiān)

9、控其對于目的地的進展?fàn)顩r。這個范例模擬了這種類型的跟蹤應(yīng)用程序,它的用戶界面如圖17-1所示。圖中展示了四個卡車,它們到達(dá)各個不同的終點(通過活動卡車列表顯示出來)。所有卡車自身都是動態(tài)的,它們從起點移動到終點。當(dāng)它們到達(dá)各自的終點時,它們會被從活動卡車的列表中移除。圖17-1TruckTracker應(yīng)用程序用戶界面你會看到每一輛卡車都由它自己的工作流實例支持。工作流定時、異步地對卡車的地理位置進行更新。當(dāng)更新進行的時候,工作流和應(yīng)用程序會為計算新的坐標(biāo)進行通信,然后可視化地在用戶界面中對卡車的位置進行更新。當(dāng)然,我們正模擬的是GPS的接受效果,所模擬卡車的移動速度遠(yuǎn)遠(yuǎn)大于實際的卡車能夠達(dá)到的

10、速度。(運行本范例4天時間后才去看卡車是否真正從加利福尼亞抵達(dá)新澤西是非常愚蠢的行為。)應(yīng)用程序真正關(guān)鍵的地方是當(dāng)和宿主應(yīng)用程序進行數(shù)據(jù)通信時使用了相關(guān)的工作流實例??ㄜ嚢凑罩付ǖ穆肪€向它們各自的終點前進,它會在地圖上穿越其它城市。當(dāng)你點擊“Add Truck”后,通過如下圖17-2所顯示的對話框,你可以選擇卡車的路線。卡車的路線都保存在一個XML文件中,當(dāng)應(yīng)用程序加載時把它們讀出來。例如,此行從薩克拉門托到特倫頓,卡車將穿過鳳凰城,圣菲,奧斯汀,以及塔拉哈西。圖17-2 “Add Truck”對話框主應(yīng)用程序現(xiàn)在已經(jīng)為你完成了,剩下的任務(wù)是要完成對應(yīng)的服務(wù)和工作流。我們首先將創(chuàng)建服務(wù)接口。為

11、你的應(yīng)用程序添加相關(guān)通信接口1.本范例同樣為你提供了兩個版本:完整版本和非完整版本。你需要下載本章源代碼,打開“TruckTracker”目錄中的解決方案。2.本解決方案包含兩個項目:TruckTracker(主應(yīng)用程序)和TruckService。在Visual Studio的解決方案資源管理器中找到TruckService項目,打開ITruckService.cs文件準(zhǔn)備進行編輯。3.在接口的大括號中,添加下面這些代碼:/ Workflow to host communicationCorrelationInitializervoid ReadyTruck(Int32 truckID, I

12、nt32 startingX, Int32 startingY);void UpdateTruck(Int32 truckID, Int32 X, Int32 Y);void RemoveTruck(Int32 truckID);/ Host to workflow communicationCorrelationAlias(truckID, e.TruckID)event EventHandler CancelTruck;CorrelationInitializerCorrelationAlias(truckID, e.TruckID)event EventHandler AddTruck;

13、4.正好在ExternalDataExchange特性的前面(你會發(fā)現(xiàn)它用來對接口進行修飾),插入CorrelationParameter特性。CorrelationParameter(truckID)5.保存本文件。回頭看看你在第3步所添加的代碼,它也被復(fù)制到了列表17-1中,你能看到在本章中所討論過的每一個特性。名稱為truckID的方法參數(shù)傳遞一個唯一的卡車標(biāo)識符,它存在于該接口的所有方法中。然后,CorrelationParameter特性通知WF這個方法參數(shù)的作用是為了關(guān)聯(lián)。列表17-1 ITruckService.cs的完整代碼ITruckService接口的完整代碼using S

14、ystem;using System.Collections.Generic;using System.Text;using System.Workflow.ComponentModel;using System.Workflow.Activities;namespace TruckServiceCorrelationParameter(truckID)ExternalDataExchangepublic interface ITruckService/ Workflow to host communicationCorrelationInitializervoid ReadyTruck(In

15、t32 truckID, Int32 startingX, Int32 startingY);void UpdateTruck(Int32 truckID, Int32 X, Int32 Y);void RemoveTruck(Int32 truckID);/ Host to workflow communicationCorrelationAlias(truckID, e.TruckID)event EventHandler CancelTruck;CorrelationInitializerCorrelationAlias(truckID, e.TruckID)event EventHan

16、dler AddTruck;AddTruck和CancelTruck兩個事件使用了一個CorrelationAlias特性來把關(guān)聯(lián)參數(shù)的名稱由truckID重新指定為e.TruckID,因為事件參數(shù)(arguments)為這些事件攜帶了關(guān)聯(lián)標(biāo)識符。對于本范例來說使用的是e.TruckID,但是任何事件參數(shù)(argument)都能被用來攜帶關(guān)聯(lián)參數(shù)。也就是說,你能把truckID的別名指定為任何也攜帶了關(guān)聯(lián)值到工作流中去的參數(shù)。在這個接口中有兩種來對關(guān)聯(lián)機制進行初始化的方式:工作流可以調(diào)用ReadyTruck,或者宿主應(yīng)用程序調(diào)用AddTruck事件。任何一個都會開始進行相關(guān)通信(correla

17、ted communications),因為兩者都使用了CorrelationInitializer特性進行修飾。在此之前調(diào)用任何其它的方法或者事件進行初始化其結(jié)果是工作流運行時產(chǎn)生異常。服務(wù)項目通常都帶有本地通信服務(wù),這個范例的應(yīng)用程序也并沒有什么不同。因為連接器(connector)類TruckServiceDataConnector由ITruckService派生,因此現(xiàn)在是該完成它的時候了。完成關(guān)聯(lián)的數(shù)據(jù)連接器(correlated data connector)1.再次回到TruckService項目,找到TruckServiceDataConnector.cs文件并打開它準(zhǔn)備進行編

18、輯。2.TruckServiceDataConnector類現(xiàn)在是空的,但是它明顯派生自ITruckService。因此,你至少要把接口中的方法和事件添加到這個類中。但是在你完成這些之前,我們先添加一些需要的代碼。首先,正好在這個類的左大括號后面添加下面的字段。protected const string KeyFormat = 0.Truck_1;protected static Dictionary _dataValues = new Dictionary();protected static Dictionary _dataServices =new Dictionary();priva

19、te static object _syncLock = new object();3.因為數(shù)據(jù)連接器需要與數(shù)據(jù)項保存聯(lián)系并且在工作流運行時中是一個單例模式(singleton),因此我們將添加一對靜態(tài)方法,它們用來對數(shù)據(jù)服務(wù)進行注冊并對已經(jīng)注冊的數(shù)據(jù)服務(wù)進行檢索。WorkflowTruckTrackingDataService方法和RegisterDataService方法public static WorkflowTruckTrackingDataService GetRegisteredWorkflowDataService(Guid instanceID,Int32 truckID)s

20、tring key = String.Format(KeyFormat, instanceID, truckID);WorkflowTruckTrackingDataService serviceInstance = null;if (_dataServices.ContainsKey(key)/ Return the appropriate data serviceserviceInstance = _dataServiceskey;return serviceInstance;public static void RegisterDataService(WorkflowTruckTrack

21、ingDataService dataService)string key = String.Format(KeyFormat, dataService.InstanceID.ToString(), dataService.TruckID);lock (_syncLock)_dataServices.Add(key, dataService);4.當(dāng)一個新的工作流實例被啟動的時候,在主應(yīng)用程序中都要對數(shù)據(jù)服務(wù)進行注冊(每個工作流實例對應(yīng)一個數(shù)據(jù)服務(wù)),一旦數(shù)據(jù)服務(wù)被注冊后,它就在數(shù)據(jù)連接器中保存關(guān)聯(lián)數(shù)據(jù)。我們需要有一個去檢索該數(shù)據(jù)的方式。以前,我們使用的是一個屬性,但是對于我們現(xiàn)在來說這已經(jīng)不

22、適用了,因為我們必須傳入工作流實例ID和關(guān)聯(lián)值(在本例中是一個卡車的標(biāo)識符)二者。為了檢索該數(shù)據(jù),在靜態(tài)的注冊方法(RegisterDataService方法)的下面添加如下這個方法:RetrieveTruckInfo方法public string RetrieveTruckInfo(Guid instanceID, Int32 truckID)string payload = String.Empty;string key = String.Format(KeyFormat, instanceID, truckID);if (_dataValues.ContainsKey(key)paylo

23、ad = _dataValueskey;return payload;5.有了這最后的一個方法后,我們現(xiàn)在就去添加來自于ITruckService接口的方法。它們的位置緊跟在前一步驟所添加的檢索數(shù)據(jù)的方法下面。繼承自ITruckService接口的方法/ Workflow to host communication methodspublic void ReadyTruck(Int32 truckID, Int32 startingX, Int32 startingY)/ Pull correlated serviceWorkflowTruckTrackingDataService servi

24、ce =GetRegisteredWorkflowDataService(WorkflowEnvironment.WorkflowInstanceId,truckID);/ Place data in correlated storeUpdateTruckData(service.InstanceID, truckID, startingX, startingY);/ Raise the event to trigger host activityif (service != null)service.RaiseTruckLeavingEvent(truckID, startingX, sta

25、rtingY);public void UpdateTruck(Int32 truckID, Int32 X, Int32 Y)/ Pull correlated serviceWorkflowTruckTrackingDataService service =GetRegisteredWorkflowDataService(WorkflowEnvironment.WorkflowInstanceId,truckID);/ Update data in correlated storeUpdateTruckData(service.InstanceID, truckID, X, Y);/ Ra

26、ise the event to trigger host activityif (service != null)service.RaiseRouteUpdatedEvent(truckID, X, Y);public void RemoveTruck(Int32 truckID)/ Pull correlated serviceWorkflowTruckTrackingDataService service =GetRegisteredWorkflowDataService(WorkflowEnvironment.WorkflowInstanceId,truckID);/ Remove t

27、ruck from correlated storestring key = String.Format(KeyFormat, service.InstanceID, truckID);if (_dataValues.ContainsKey(key)/ Remove it_dataValues.Remove(key);/ Raise the event to trigger host activityif (service != null)service.RaiseTruckArrivedEvent(truckID);6.在ITruckService中的方法的后面是一些事件,因此也要添加它們,

28、它們的位置在你第5步所添加的方法的下面。繼承自ITruckService接口的事件/ Host to workflow eventspublic event EventHandler CancelTruck;public void RaiseCancelTruck(Guid instanceID, Int32 truckID)if (CancelTruck != null)/ Fire eventCancelTruck(null, new CancelTruckEventArgs(instanceID, truckID);public event EventHandler AddTruck;p

29、ublic void RaiseAddTruck(Guid instanceID, Int32 truckID, Int32 routeID)if (AddTruck != null)/ Fire eventAddTruck(null, new AddTruckEventArgs(instanceID, truckID, routeID);7.回頭看看在第5步中插入的方法,你會看到一個用來把關(guān)聯(lián)數(shù)據(jù)插入到對應(yīng)的數(shù)據(jù)字典中去的方法(UpdateTruckData)。數(shù)據(jù)本身必須被轉(zhuǎn)換為XML,因此以其把下面這些代碼都擴散到上面的三個方法中,那還不如添加一個UpdateTruckData方法,然后

30、把它們都放在UpdateTruckData方法中?,F(xiàn)在就添加該方法,把它放在你前面添加的事件的下面:UpdateTruckData方法protected Truck UpdateTruckData(Guid instanceID, Int32 truckID, Int32 X, Int32 Y)string key = String.Format(KeyFormat, instanceID, truckID);Truck truck = null;if (!_dataValues.ContainsKey(key)/ Create new trucktruck = new Truck();tru

31、ck.ID = truckID;else/ Pull existing truckstring serializedTruck = _dataValueskey;StringReader rdr = new StringReader(serializedTruck);XmlSerializer serializer = new XmlSerializer(typeof(Truck);truck = (Truck)serializer.Deserialize(rdr);/ Update valuestruck.X = X;truck.Y = Y;/ Serialize valuesStringB

32、uilder sb = new StringBuilder();using (StringWriter wtr = new StringWriter(sb)XmlSerializer serializer = new XmlSerializer(typeof(Truck);serializer.Serialize(wtr, truck);/ Ship the data back_dataValueskey = sb.ToString();return truck;8.保存該文件。列表17-2中列出了TruckServiceDataConnector類的完整代碼。在強調(diào)一次,這個類的作用是保存來

33、自各個工作流實例的關(guān)聯(lián)數(shù)據(jù)。該數(shù)據(jù)被存儲到一個Dictionary對象中,鍵值對把工作流實例標(biāo)識符和卡車標(biāo)識符關(guān)聯(lián)起來。該數(shù)據(jù)連接器類在工作流運行時中是一個單例服務(wù)。備注:你可能會問:為什么數(shù)據(jù)要轉(zhuǎn)換為XML而不直接使用數(shù)據(jù)對象本身?這是因為,當(dāng)在工作流和宿主之間來回傳送數(shù)據(jù)的時候,WF并不對對象進行序列化。因此,并不會創(chuàng)建對象的副本(毫無疑問是為了提高性能)。對象的傳遞是通過引用實現(xiàn)的,由此工作流和宿主都在同一個對象上工作。假如你不想這樣(注:指對象引用),又不想使用本范例中的方法(注:指轉(zhuǎn)換為XML)的話,你就可以對對象進行序列化或者實現(xiàn)ICloneable來傳遞對象的副本。假如這種行為(

34、注:指對象引用)并不影響你的設(shè)計,你就不需要再去做任何事情而直接(在工作流和宿主之間)來回通過引用的方式去傳遞你的對象。雖然如此,也要牢記你的對象將會被兩個不同的線程所共享。列表17-2 TruckServiceDataConnector.cs的完整代碼TruckServiceDataConnector類的完整代碼using System;using System.Collections.Generic;using System.Text;using System.Threading;using System.Workflow.Activities;using System.Workflow.

35、Runtime;using System.Xml;using System.Xml.Serialization;using System.IO;namespace TruckServicepublic class TruckServiceDataConnector : ITruckServiceprotected const string KeyFormat = 0.Truck_1;protected static Dictionary _dataValues = new Dictionary();protected static Dictionary _dataServices = new

36、Dictionary();private static object _syncLock = new object();public static WorkflowTruckTrackingDataService GetRegisteredWorkflowDataService(Guid instanceID, Int32 truckID)string key = String.Format(KeyFormat, instanceID, truckID);WorkflowTruckTrackingDataService serviceInstance = null;if (_dataServi

37、ces.ContainsKey(key)/ Return the appropriate data serviceserviceInstance = _dataServiceskey; / ifreturn serviceInstance;public static void RegisterDataService(WorkflowTruckTrackingDataService dataService)string key = String.Format(KeyFormat, dataService.InstanceID.ToString(), dataService.TruckID);lo

38、ck (_syncLock)_dataServices.Add(key, dataService); / lockpublic string RetrieveTruckInfo(Guid instanceID, Int32 truckID)string payload = String.Empty;string key = String.Format(KeyFormat, instanceID, truckID);if (_dataValues.ContainsKey(key)payload = _dataValueskey; / ifreturn payload;/ Workflow to

39、host communication methodspublic void ReadyTruck(Int32 truckID, Int32 startingX, Int32 startingY)/ Pull correlated serviceWorkflowTruckTrackingDataService service = GetRegisteredWorkflowDataService(WorkflowEnvironment.WorkflowInstanceId, truckID);/ Place data in correlated storeUpdateTruckData(servi

40、ce.InstanceID, truckID, startingX, startingY);/ Raise the event to trigger host activityif (service != null)service.RaiseTruckLeavingEvent(truckID, startingX, startingY); / ifpublic void UpdateTruck(Int32 truckID, Int32 X, Int32 Y)/ Pull correlated serviceWorkflowTruckTrackingDataService service = G

41、etRegisteredWorkflowDataService(WorkflowEnvironment.WorkflowInstanceId, truckID);/ Update data in correlated storeUpdateTruckData(service.InstanceID, truckID, X, Y);/ Raise the event to trigger host activityif (service != null)service.RaiseRouteUpdatedEvent(truckID, X, Y); / ifpublic void RemoveTruc

42、k(Int32 truckID)/ Pull correlated serviceWorkflowTruckTrackingDataService service = GetRegisteredWorkflowDataService(WorkflowEnvironment.WorkflowInstanceId, truckID);/ Remove truck from correlated storestring key = String.Format(KeyFormat, service.InstanceID, truckID);if (_dataValues.ContainsKey(key)/ Remove it_dataValues.Remove(key); / if/ Raise the event to trigger host activityif (service != null)service.RaiseTruckArrive

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論