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

相关文章
相关标签/搜索