.net remoting 拋出異常

本文告訴你們如何在使用 .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 特性code

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

    }       
 }

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

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

    }       
 }

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

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

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)進行處理和處理如何序列化。處理如何序列化能夠提升性能,由於本身知道哪些須要序列化,哪些不須要。

 

相關文章
相關標籤/搜索