在客户端中未定义的远程处理服务器上引发异常会导致“无法找到程序集”异常

问题描述

我有一些客户端代码使用

通过远程处理调用方法
myProxy = (IProxy)Activator.Getobject(
                    typeof(IProxy),"tcp://" + address + ":" + theControllerPort + "/Proxy");

IProxy 定义为

    public interface IProxy  {
        void DoStuff();
    }

代理定义为

    public class Proxy : MarshalByRefObject,IProxy {
        public void DoStuff() {
            throw new DerivedException();
        }
    }

我有一个名为 DerivedException 的异常定义为

    [Serializable]
    public class DerivedException: ApplicationException {
        public DerivedException() : base () { }

        public DerivedException(string message) : base (message) { }
        public DerivedException(string message,Exception innerException) : base (message,innerException) { }
        protected DerivedException(SerializationInfo info,StreamingContext context) : base(info,context) { }
    }

当我调用 myProxy.DoStuff()

try{
    result = myProxy.DoStuff();
}
catch (Exception ex) {
    myLog.Error("Error",ex);
}

我得到一个例外:

"Unable to find assembly 'xyz,Version=123,Culture=neutral,PublicKeyToken=null'."

  at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData,Int32 type)
...

我认为我的客户端代码应该能够反序列化抛出的 DerivedException,因为 DerivedException 继承自 Exception 并且客户端代码设置为捕获 Exception。我在这里做错了什么?如果我在客户端代码的 bin/debug 文件夹中包含定义 DerivedException 的 .dll,则客户端会正确接收异常。有没有其他方法可以让这个异常反序列化并被客户端代码正确捕获?

解决方法

该问题与您的 Proxy 派生自 MarshalByRefObject 的事实有关,并且在这种情况下,对象引用从一个应用程序域传递到另一个应用程序域,而不是对象本身。

另一方面,您的 DerivedException 被标记为 Serializable。当类标记为 Serializable 时,它将自动序列化,从一个应用程序域传输到另一个应用程序域,然后反序列化以在第二个应用程序域中生成对象的精确副本。

我会尝试将 Proxy 类标记为 Serializable。当此对象与远程处理一起使用时,负责序列化的格式化程序会控制序列化过程,并用代理替换从 MarshalByRefObject 派生的所有对象。

,

您需要在客户端上也定义了 DerivedException 的程序集:在服务器上抛出异常、序列化并发送到客户端。客户需要知道那个 DerivedException 是什么。

一种常见的处理方法是在客户端和服务器上安装一个共享程序集,您可以使用相同的程序集,您为此定义了 IProxy

相反,定义了 Proxy 的程序集仅在服务器中需要