问题描述
通过远程处理调用方法
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
的程序集仅在服务器中需要