• [Remoting FAQ]传递Remoting参数时遇到的两种常见错误


    [Remoting FAQ]

    传递Remoting参数时遇到的两种常见错误

    Version

    Date

    Creator

    Description

    1.0.0.1

    2006-4-25

    郑昀@Ultrapower

    草稿

     

    继续阅读之前,我们假设您熟悉以下知识:

    n         Remoting

    [现象1]

    我们先来描述一个简单的错误。当你激活远端Remoting Objects时,却得到了这样的错误提示:

    提示信息

    Type 'Common.BTRequest' in Assembly

    'Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'

    is not marked as serializable.

    这个错误很容易理解。就是你的Remoting Method用到了一个输入参数,这个输入参数声明为“Common.BTRequest”类,它没有做序列化。

    [解决1]

    很简单。

    在你的BTRequest类前面加一行:

    [Serializable]

    public class BTRequest

    即可。

    [背景资料1]

    Piet Obermeyer的《.NET 中的对象序列化》讲解得非常详细:

    微软资料

    由正在进行序列化的对象所引用的所有对象都必须标记为 Serializable(请参阅基本序列化)。否则,当序列化程序试图序列化未标记的对象时将会出现异常。

     

    对象仅在创建对象的应用程序域中有效。除非对象是从 MarshalByRefObject 派生得到或标记为 Serializable,否则,任何将对象作为参数传递或将其作为结果返回的尝试都将失败。如果对象标记为 Serializable,则该对象将被自动序列化,并从一个应用程序域传输至另一个应用程序域,然后进行反序列化,从而在第二个应用程序域中产生出该对象的一个精确副本。此过程通常称为按值封送。

     

    [现象2]

    下面这个错误比较诡异,而且不是通常大家所解决掉的那种错误。当你激活远端Remoting Objects时,却得到了这样的错误提示:

    提示信息

    Because of security restrictions, the type System.Runtime.Remoting.ObjRef cannot be accessed.

    最开始被误导到我的另一篇文章《[Remoting]dotNet Framework升级后Remoting信道使用的安全问题》,这篇文章中谈到的“typeFilterLevel="Full"”解决问题方式在

    http://www.ingorammer.com/remotingFAQ/changes2003.html

    http://www.codeproject.com/csharp/PathRemotingArticle.asp

    http://msdn2.microsoft.com/en-us/library/61w7kz4b.aspx

    都论述过了。

    但是,这次情况却不一样。

    我并不是framework1.0编译的东西在framework1.1环境下使用,而且把Remoting配置文件中修改为:

    <channels>

            <channel ref="http" />

            <serverProviders>

              <provider ref="wsdl" />

              <formatter ref="binary" typeFilterLevel="Full" />

            </serverProviders>

    </channels>

    最终也无济于事。

     

    [解决2]

    注意到我Remoting Method用到了BTRequest的输入参数,它却继承了MarshalByRefObject接口。这就是问题之所在。

    也就是说,如果我的一个输入参数类这么声明:

    public class BTRequest : MarshalByRefObject

    前面加不加“[Serializable]”的标记都无所谓,都可以让客户端得到异常:

    提示信息

    Because of security restrictions, the type System.Runtime.Remoting.ObjRef cannot

     be accessed.

     

    Server stack trace:

       at System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject(

    Type type)

       at System.Runtime.Serialization.Formatters.Soap.ObjectReader.ParseObject(Pars

    eRecord pr)

       at System.Runtime.Serialization.Formatters.Soap.ObjectReader.Parse(ParseRecor

    d pr)

       at System.Runtime.Serialization.Formatters.Soap.SoapHandler.StartChildren()

       at System.Runtime.Serialization.Formatters.Soap.SoapParser.ParseXml()

       at System.Runtime.Serialization.Formatters.Soap.SoapParser.Run()

    只要不让这个输入参数类继承MarshalByRefObject接口就好了!

    [背景资料2]

    Piet Obermeyer的《.NET 中的对象序列化》讲到:

    微软资料

    如果对象是从 MarshalByRefObject 派生得到,则从一个应用程序域传递至另一个应用程序域的是对象引用,而不是对象本身。也可以将从 MarshalByRefObject 派生得到的对象标记为 Serializable远程使用此对象时,负责进行序列化并已预先配置为 SurrogateSelector 的格式化程序将控制序列化过程,并用一个代理替换所有从 MarshalByRefObject 派生得到的对象。如果没有预先配置为 SurrogateSelector,序列化体系结构将遵从下面的标准序列化规则(请参阅序列化过程的步骤)。

    那既然我愿意传递对象引用,那么为什么在配置文件上配置typeFilterLevel不起作用呢?

    服务器端配置:

    <channels>

            <channel ref="http" />

            <serverProviders>

              <provider ref="wsdl" />

              <formatter ref="binary" typeFilterLevel="Full" />

            </serverProviders>

    </channels>

    客户端配置:

    <channels>

            <channel ref="http" />

              <clientProviders>

                <formatter ref="binary"/>

              </clientProviders>

              <serverProviders>

                <formatter ref="binary" typeFilterLevel="Full" />

              </serverProviders>

    </channels>

     

  • 相关阅读:
    如何用grep命令同时显示匹配行上下的n行 (美团面试题目)
    Maven面试宝典
    Java经典设计模式 总览
    Java设计模式之工厂模式
    Java设计模式
    三次握手,四次挥手 具体发送的报文和状态都要掌握(阿里)
    运动与饮食结合
    健身计划
    Java中的多线程=你只要看这一篇就够了
    js禁止复制粘贴
  • 原文地址:https://www.cnblogs.com/zhengyun_ustc/p/remoting_client_exceptions_2.html
Copyright © 2020-2023  润新知