一、 技術要點
我們都知道Windows應用程式在運行時會啟動一個進程,其總包括若干線程,不同的進程之間通訊是開發分布式應用程式所必需的,傳統上,這不僅需要深入瞭解通訊流兩端上進程的對象,而且還要深入瞭解低層級協議的宿主、API以及組態工具等。總之,它是一項需要大量專業知識和經驗的複雜任務。
幸好.Net為我們提供了遠端功能,它所提供的通訊方法可以快速而方便地完成上述建立通訊的任務。因此,無論是需要快速開發 Web 應用程式,還是要花費更多時間產生關鍵的企業範圍的應用程式,.NET Framework 都會提供支援。通過 .NET 遠端,用戶端應用程式可以使用同一台電腦或其網路中其他任何可用的電腦上的其他進程中的對象。
要使用 .NET 遠端建立可以讓兩個對象跨越應用程式直接通訊的應用程式,只需產生以下對象即可:
1、 可遠端的對象。
2、 偵聽對該遠程對象的請求的應用程式即伺服器程式。
3、 對該遠程對象發出請求的用戶端應用程式。
.Net下不同應用程式中的對象的通訊方式有兩種:一種是跨應用程式定義域邊界傳輸對象副本,一種是使用代理交換訊息。MarshalByRefObject 是通過使用代理交換訊息來進行通訊的對象的基類。當跨應用程式使用遠程對象時,對象的基類必須是從 MarshalByRefObject 繼承。
二、 程式實現
(1)我們先在VS的IDE中建立名為“TestRemoteAccess”的新的解決方案來容納前述用來實現遠端的三個項目,首先向解決方案中添加名為“RemoteObject”的類庫,然後將預設建立的類名更改為“CRemoteAccess”,並且繼承於“MarshalByRefObject”,代碼如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace RemoteObject
{
public class CRemoteAccess : MarshalByRefObject
{}
}
我們需要在該對象內建立用於串連和存取本地Access資料庫的所有函數,供服務端用戶端程式同時調用。用於串連和存取Access資料庫的方法這裡不再詳述,參看附件源碼。
首先所有需要向用戶端公開的函數其可見度都必須設為 public。變數m_ConnString需要設定為public static,目的是當用戶端調用了SetRemoteAccessConnString後將資料庫連接字串儲存下來以備在本次串連期間始終能夠訪問,代碼如下:
……
public static string m_ConnString;
……
public void SetRemoteAccessConnString(string Connstr)
{
m_ConnString = Connstr;
}
……
成功串連了Access資料庫後我們需要返回資料集給請求的用戶端進行顯示和編輯,在遠程對象中我們聲明了幾個相關函數:
private void LoadData(string SqlStr, string TableName)
public void SaveData(DataTable ClientDataTable)
public DataTable GetUserTable(string SqlStr, string TableName)
用戶端可以傳遞SQL查詢指令碼通過調用 GetUserTable來擷取相關資料庫表的資料,並返回一個DataTable,然後可以將該DataTable附值給DataGridView以便將資料顯示出來。GetUserTable通過調用私人的LoadData 函數來完成對資料的擷取。SaveData函數用於將編輯過的資料集儲存回本地Access資料庫檔案,代碼如下:
……
m_connection.Open();
m_adapter.Update(ClientDataTable);
……
(2)遠程對象建立完成,我們需要建立用於偵聽該遠程對象請求的服務端應用程式。在“TestRemoteAccess”解決方案中建立一個Windows表單項目名為:“TestServer”,從工具箱中拖拽下幾個組件,介面如下所示:
伺服器程式TestServer除了具備遠端存取對象的能力外,它最主要的作用就是擷取實際的Access資料庫檔案路徑,並且設定遠程對象的資料庫連接字串。我們必須添加遠程對象以及遠端和網路通訊協議等的類庫的引用。在伺服器程式啟動初始,需要建立遠程對象的執行個體以及註冊通訊連接埠,然後調用RemotingConfiguration.RegisterWellKnownServiceType 方法,MSDN中關於該方法的描述是這樣的:通過使用給定的參數初始化 WellKnownServiceTypeEntry 的新執行個體,將服務端上的對象 Type 註冊為已知類型,所有知道登入已知對象的 URI 的客戶都可以擷取該對象的代理。所謂URI即統一資源識別項 (Uniform Resource Identifier)。代碼如下:
……
remotableObject = new RemoteObject.CRemoteAccess();
TcpChannel channel = new TcpChannel(8080);
ChannelServices.RegisterChannel(channel);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemoteObject.CRemoteAccess), "RithiaTestAccessServer", WellKnownObjectMode.Singleton);
……
當選擇了要進行存取的Access資料庫檔案後,我們需要調用遠程對象的SetRemoteAccessConnString方法,該方法將儲存在本次與伺服器程式串連期間串連該Access資料庫檔案的連接字串,代碼如下:
……
ProviderStr = ProviderStrPart + txtAccessMdbFileName.Text + ";Jet OLEDB:Database Password=" + txtAccessPassword.Text;
……
remotableObject.SetRemoteAccessConnString(ProviderStr);
……
(3)最後我們建立用於串連和請求服務的用戶端程式,它會通過調用伺服器程式TestServer已經註冊的遠程對象來擷取相關資料集,並將編輯過的資料儲存回實際的資料庫檔案。在“TestRemoteAccess”解決方案中建立一個Windows表單項目名為:“TestClient”,從工具箱中拖拽下幾個組件,介面如下所示:
用戶端程式需要知道伺服器程式所運行在的電腦名稱或IP地址以及偵聽的連接埠號碼,然後建立遠程對象的執行個體,並且建立DataTable以便接收返回的資料,代碼如下:
……
string RemoteURL;
Host = txtHost.Text;
Port = txtPort.Text;
RemoteURL = "tcp://" + Host + ":" + Port + "/RithiaTestAccessServer";
try
{
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
remoteObject = (RemoteObject.CRemoteAccess)Activator.GetObject(typeof(RemoteObject.CRemoteAccess), RemoteURL);
RemoteDataTable = new DataTable();
button3.Enabled = false;
}
catch (Exception E)
{
MessageBox.Show(E.Message.ToString());
}
finally
{
}
……
用戶端程式根據服務程式所偵聽的通道是TCP還是HTTP來註冊相應的通道和連接埠號碼,並且組合成遠程對象的Url,即Url= 通道://主機名稱:連接埠號碼/對象的Uri,然後建立遠程對象的執行個體,就像使用本機物件一樣可以對其進行存取,我們可以調用遠程對象的GetUserTable方法擷取指定查詢指令碼的結果集,代碼如下:
……
RemoteDataTable = remoteObject.GetUserTable(txtSQL.Text, "Test");
dataGridView1.DataSource = RemoteDataTable;
……
儲存結果集時僅需簡單調用SaveData方法即可,代碼如下:
……
remoteObject.SaveData(RemoteDataTable);
……
三、 結果
該程式成功地在Visual Studio .Net 2005及Windows XP SP2下調試運行通過。
源碼下載:http://d.download.csdn.net/down/401452/q520525745