dotnetremoting拋出異常

title author date CreateTime categories
dotnet remoting 拋出異常
lindexi
2019-09-24 15:39:50 +0800
2018-04-02 11:27:43 +0800
.net remoting rpc WPF

本文告訴你們如何在使用 .net remoting 的時候,拋出異常。json

全部在遠程軟件運行的類,若是須要傳輸到本地,都須要繼承 MarshalByRefObject 或其餘能夠序列化的類。ide

在 .net Framework 4.0 就默認指定只反序列化基礎類型,若是須要反序列化其餘的類型,那麼就須要設置TypeFilterLevel,設置的方法是在使用下面代碼函數

      public static IChannel CreatChannel(string port = "")
        {
            if (string.IsNullOrEmpty(port))
            {
                port = Guid.NewGuid().ToString("N");
            }

            var serverProvider = new SoapServerFormatterSinkProvider();
            var clientProvider = new SoapClientFormatterSinkProvider();
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full;
            IDictionary props = new Hashtable();
            props["portName"] = port.ToString();

            return new IpcChannel(props, clientProvider, serverProvider);
        }

可是設置了TypeFilterLevel不是對全部的類型均可以進行轉換,若是不當心直接在調用方法拋出異常,那麼會由於沒法反序列,讓本地拿不到性能

 // 遠程

 public void Foo()
 {
 	throw new CsdnNotFoundException();
 }

 public class CsdnNotFoundException : Exception
 {
 	public CsdnNotFoundException(string str) :
 	       base(str)
 	{

 	}       
 }

這時本地會提示System.Runtime.Serialization.SerializationException程序沒法序列。ui

若是須要在 .net remoting 使用異常,那麼須要本身建立一個異常,繼承 RemotingException.net

反序列

由於默認的 RemotingException 沒有反序列,因此須要添加 Serializable 特性orm

 [Serializable]
 public class CsdnNotFoundException : RemotingException
 {
 	public CsdnNotFoundException(string str) :
 	       base(str)
 	{

 	}       
 }

微軟建議繼承ISerializable,標記特性server

 [Serializable]
 public class CsdnNotFoundException : RemotingException, ISerializable
 {
 	public CsdnNotFoundException(string str) :
 	       base(str)
 	{

 	}       
 }

若是直接運行,會發現報告System.Runtime.Serialization.SerializationException:「未找到反序列化「lindexi.Csdn.CsdnNotFoundException」類型對象的構造函數對象

解決方法是建立一個構造函數,寫入這個函數就不須要再寫其餘的代碼。blog

        protected CsdnNotFoundException([NotNull] SerializationInfo info, StreamingContext context) : base(info,
            context)
        {
        }

若是有一些特殊的屬性須要本身設置,建議建立一個默認構造函數,和兩個方法,由於使用上面的方法不會序列化本身定義的屬性。

 [Serializable]
 public class CsdnNotFoundException : RemotingException, ISerializable
 {
    public CsdnNotFoundException()
    {
    	//默認構造,能夠在反射建立
    }

 	public CsdnNotFoundException(string str) :
 	       base(str)
 	{

 	}      

 	      protected CsdnNotFoundException([NotNull] SerializationInfo info, StreamingContext context) 
 	      //: base(info, context) 不使用基類的緣由是基類會報告 找不到 ClassName 和其餘不少的坑
        {
            //反序列化建立

            Message = (string) info.GetValue(MessageSerialization, typeof(string));
        } 

        // 重寫消息,用於在構造設置值
        public override string Message { get; }

        // 用於在構造拿到消息的值
        private const string MessageSerialization = "Message";

        // 重寫這個方法,在序列化調用
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(MessageSerialization, Message);
        }
 }

在 GetObjectData 拿到必要的屬性,這個須要本身把須要的屬性寫入。而後在構造函數重寫[NotNull] SerializationInfo info, StreamingContext context方法的,能夠拿到值

由於上面的代碼用到 Message ,須要重寫這個屬性,由於默認是隻讀,不能在構造函數設置。

是否是以爲很複雜,實際上簡單的方法是經過 json 在GetObjectData把類轉換爲json,在構造轉換爲類。

ISerializable

那麼爲何在使用 Serializable 特性還須要繼承 ISerializable ,由於繼承 ISerializable 就能夠在一個構造函數xx([NotNull] SerializationInfo info, StreamingContext context)進行處理和處理如何序列化。處理如何序列化能夠提升性能,由於本身知道哪些須要序列化,哪些不須要。

關於 ISerializable 請看

How to: Create an Exception Type That Can be Thrown by Remote Objects

相關文章
相關標籤/搜索