本文告訴你們如何在使用 .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,在構造轉換爲類。
那麼爲何在使用 Serializable 特性還須要繼承 ISerializable ,由於繼承 ISerializable 就能夠在一個構造函數xx([NotNull] SerializationInfo info, StreamingContext context)進行處理和處理如何序列化。處理如何序列化能夠提升性能,由於本身知道哪些須要序列化,哪些不須要。