.net remoting 文章

.net remoting 框架簡介http://www.g2host.cn/www/Article/Program/Net/200701/10786.html

How to monitor if Remote Objects have been deployed successfully
 
在調試.Net Remoting程序時,經常會出現一些莫名其妙的問題,IDE提示的異常信息有時也不一定正確。很多時候都是自己粗心,配置configuration文件上出了問題,包括ClientServer端的配置文件。另外,我感覺.Net Remoting中還有許多陷阱(trap),如前面postingSoapSuds工具的一些不足之處》所提及的,不只這些,還有許多。如果陷入這些trap,而且又不知道的話,就麻煩了,調試半天也不知道問題在哪裏。有空的時間,我準備花些時間整理一下.Net Remoting中的trap
 
言歸正傳,這裏看看如何檢測Remote Objects是否部署成功。Remote Objects部署成功是第一步,否則Client端調用Remote Objects肯定會拋異常信息了。因此,如出現異常信息,首先檢測Remote Objects是否成功部署在Server端。
 
下面根據激活類型分兩種情況:SAO(服務端激活對象)和CAO(客戶端激活對象)。
 
1SAO對象
SAO對象而言,比較簡單。根據Server端配置文件中<wellknown>節或RemotingConfiguration.RegisterWellKnownServiceType()方法中指定的URL,通過IE瀏覽器檢測,如下所示:
http://<hostname>:<port>/<ApplicationName>/<URL>?wsdl
如果IE返回WSDL信息,則顯示Remote Objects部署成功。其實只要看到IE有正確返回信息就行了,如果你瞭解WSDLWeb Services Description Language),可以進一步看看是否調用的Remote Method是否有出現。
 
需要注意的地方:
1)如果Remote Objects部署在IIS中,<ApplicationName>則爲虛擬目錄名稱(Virtual Directory Name),並且不要在Web.Config配置文件中設定Application Name。同時Remote ObjectsURL需要以soaprem爲後綴名。
2)如果Remote Objects不是部署在IIS中,則必須在configuration配置文件或者在代碼中RemotingConfiguration.Application=”<ApplicationName>”來指定ApplicationName
 
2CAO對象
對於CAO對象,和SAO對象不一樣。需要如下的URL來測試:
http://<hostname>:<port>/<ApplicationName>/RemoteActivationService.rem?wsdl
 
後面是RemoteActivationService.rem,這點和SAO對象不一樣。
 
需要注意的地方:
1)在調用CAO對象時,需要在Client端的配置文件中<client>節指定Remote Objectsurl屬性。如何使用.Net Remoting的配置文件,可以參考《.Net Remoting配置文件的用法》。

 注:訪問IIS元數據庫失敗

裝了VS2005再裝IIS,結果出了些小問題
訪問IIS元數據庫失敗
思考可能是次序出了問題,解決
1、打開CMD,進入 C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727
2、輸入 aspnet_regiis.exe -i
稍等片刻,註冊成功就解決問題了。  

接着還會出現“未能創建 Mutex”的問題 
解決方法:
1、先關閉你的VS2005。
2、打開 C:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/Temporary ASP.NET Files  找到你剛纔調試的程序的名字的目錄刪除它。
3、關閉IIS服務器,重開一次。
4、用IE瀏覽一下你的程序,問題解決。

都是次序惹的禍,最好是先IIS 再VS2K5 
    最近項目開發中的傳輸數據是圍繞Remoting而召開的,所以想把所有的數據實體都定義統一的格式,於是就寫了一個基於DataTable的基類BaseModal,其他數據實體全部繼承於它。此BaseModal基類還包括了一些其他的自有的屬性,例如pageSize每頁記錄數、currentPage當前頁碼等等,代碼如下:

  1
  2文件描述
 13
 14修改記錄
 21
 22using System;
 23using System.Data;
 24using System.Text;
 25using System.Runtime.Serialization;
 26
 27namespace Colorful.Model
 28{
 29    /// <summary>
 30    /// 數據基本表
 31    /// </summary>

 32    [Serializable]
 33    public class BaseModel : DataTable
 34    {
 35        protected   int     index;          //記錄當前行
 36        protected   int     pageSize;       //每頁記錄數
 37        protected   int     currentPage;    //當前頁碼
 38        protected   int     pages;          //總頁數
 39        protected   long    totalRecord;    //總記錄數
 40        protected string description;    //其他描述,及其輔助功能
 41
 42        public int PageSize
 54
 55        public int CurrentPage
 67
 68        public int Pages
 80
 81        public long TotalRecord
 93
 94        public string Description
106
107        public string GUID
128
129        
130
131        #region public BaseModel()
132        // -----------------------------------------------------------------------------------------
133        /// <summary>
134        /// 構造函數
135        /// </summary>

136        public BaseModel()
137        {
138            index = -1;
139            pageSize = 20;
140            currentPage = 1;
141            pages = 1;
142            totalRecord = 0;
143            description = "";
144
145            Columns.Add("GUID"typeof(string));
146        }

147        // -----------------------------------------------------------------------------------------
148        #endregion

149
150        public bool MoveNext()
166
167        public bool MovePre()
183
184        public bool GoToRow(int rowIndex)
202
203        public bool GoToFirst()
220
221        public bool GoToLast()
238
239        public void Insert()
251
252        public void Delete()
270
271        }

272}

273
結果發現數據在放序列化的時候出錯,發現原來是沒有加入序列化和反序列化構造函數,雖然BaseModal繼承於DataTable,並且加入了[Serializable]樹序列化屬性,但是要實現想繼承序列化,還是要加入構造函數,於是加入:
 1#region protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
 2        // -----------------------------------------------------------------------------------------
 3        /// <summary>
 4        /// 反序列化構造函數
 5        /// </summary>
 6        /// <param name="si">反序列化所需的全部數據</param>
 7        /// <param name="context">目標描述</param>

 8        protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
 9        {
10        }

11        // -----------------------------------------------------------------------------------------
12        #endregion

13
14        #region public override void GetObjectData(SerializationInfo info, StreamingContext context)
15        // -----------------------------------------------------------------------------------------
16        /// <summary>
17        /// 序列化函數
18        /// </summary>
19        /// <param name="info">序列化所需的全部數據</param>
20        /// <param name="context">目標描述</param>

21        public override void GetObjectData(SerializationInfo info, StreamingContext context):base.GetObjectData(info, context)
22        {
23         }

24        // -----------------------------------------------------------------------------------------
25        #endregion

結果編譯,沒有任何錯誤,但是類中的屬性(pageSize等)值卻獲取不到,想了很久,發現其實道理跟前面有些類似,因爲自己加入的屬性根本就沒有“告訴”序列化函數去處理,自然而然值就丟失了,於是修改函數如下:
 1#region protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
 2        // -----------------------------------------------------------------------------------------
 3        /// <summary>
 4        /// 反序列化構造函數
 5        /// </summary>
 6        /// <param name="si">反序列化所需的全部數據</param>
 7        /// <param name="context">目標描述</param>

 8        protected BaseModel(SerializationInfo info, StreamingContext context) : base(info, context)
 9        {
10            index = info.GetInt32("index");
11            pageSize = info.GetInt32("pageSize");
12            currentPage = info.GetInt32("currentPage");
13            pages = info.GetInt32("pages");
14            totalRecord = info.GetInt64("totalRecord");
15            description = info.GetString("description");
16        }

17        // -----------------------------------------------------------------------------------------
18        #endregion

19
20        #region public override void GetObjectData(SerializationInfo info, StreamingContext context)
21        // -----------------------------------------------------------------------------------------
22        /// <summary>
23        /// 序列化函數
24        /// </summary>
25        /// <param name="info">序列化所需的全部數據</param>
26        /// <param name="context">目標描述</param>

27        public override void GetObjectData(SerializationInfo info, StreamingContext context)
28        {
29            info.AddValue("index", index);
30            info.AddValue("pageSize", pageSize);
31            info.AddValue("currentPage", currentPage);
32            info.AddValue("pages", pages);
33            info.AddValue("totalRecord", totalRecord);
34            info.AddValue("description", description);
35            base.GetObjectData(info, context);
36        }

37        // -----------------------------------------------------------------------------------------
38        #endregion

OK,一切搞定了
posted on 2006-08-29 15:10 blockhead 閱讀(1343) 評論(1)  編輯 收藏 引用 網摘 所屬分類: Remoting

FeedBack:
# re: Remoting系列專題---自定義序列化類
2006-08-29 18:16 | blockhead
剛看到一個夏桅 (xia4 wei2)提供的的技巧,在加入自定義字段,可以不用自己一個個加入,如夏桅所說:
根據我的experiance,需要自己實現ISerializable接口的情形,往往是因爲“大部分字段可以自動序列化(比如int、string),而少數字段不支持序列化(比如Thread、WaitHandle),但這些字段對於對象又是必不可少的”的需求。也就是說,這些不支持序列化的字段在反序列化後仍不允許爲空時,你得自己控制序列化/反序列化行爲,在反序列化構造函數重新建立它們的實例。

這裏的問題是,大部分字段都可以自動序列化的;但是爲了少數幾個不支持序列化的字段,卻需要編寫代碼爲所有字段都進行手工的序列化 — 這些代碼不但冗繁,而且容易出錯(比如忘掉了處理某個字段)。我一直希望能自己參與自動序列化/反序列化的行爲,比如在自動反序列化之後,運行時能自動調用一段我自己的代碼,處理那些不支持序列化的字段。

class SerializationHelper
...{
public static void Serialize(object obj, SerializationInfo info, StreamingContext context)
...{
MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), context);
foreach(FieldInfo field in members)
...{
info.AddValue(field.Name, field.GetValue(obj), field.FieldType);
}
}

public static void Deserialize(object obj, SerializationInfo info, StreamingContext context)
...{
MemberInfo[] members = FormatterServices.GetSerializableMembers(obj.GetType(), context);
foreach(FieldInfo field in members)
...{
field.SetValue(obj, info.GetValue(field.Name, field.FieldType));
}
}
}

下面是利用了這個SerializationHelper的自定義序列化方案:

[Serializable]
class Person : ISerializable
...{
// public field
public string Name = "Vista Xia";
// private field
private int age = 23;
// public property (no use in serialization)
public int Age
...{
get ...{ return age; }
set ...{ age = value; }
}
[NonSerialized]
public string Award;
// event/delegate
public event EventHandler Birthday;

public Person()
...{
Award = "MVP";
}

protected Person(SerializationInfo info, StreamingContext context)
...{
SerializationHelper.Deserialize(this, info, context);
Award = "MVP";
}

public void GetObjectData(SerializationInfo info, StreamingContext context)
...{
SerializationHelper.Serialize(this, info, context);

如有不明白處,請查看夏桅 (xia4 wei2)的Blog
http://blog.joycode.com/sunmast/  回覆  更多評論
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章