System.InvalidCastException创建使用一个强命名程序集定义的接口的较旧版本的客户端激活的对象时,客户端、接口、定义、对象

2023-09-02 02:05:45 作者:独来独往

我有关于.NET远程,版本和创建客户端激活的对象的查询。

I have a query about .Net Remoting, versioning and creating client activated objects.

下面是该方案:

有2个接口,居住在自己组装SharedTypes:iServer的和IAccount。 iServer中包含的方法的getStatus,它返回一个字符串,而CreateAccount它返回一个IAccount类型。这被登记到GAC作为V1.0.0.0

There are 2 interfaces, residing in their own assembly "SharedTypes": IServer and IAccount. IServer contains methods "GetStatus" which returns a string, and "CreateAccount" which returns an IAccount type. This is registered into the GAC as v1.0.0.0.

服务器应用程序引用SharedTypes并实现iServer的和IAccount与具体的类,服务器和客户。这是MarshalByRefObject的对象。服务器应用程序整编Server类作为一个单独的对象。

Server application references SharedTypes and implements IServer and IAccount with concrete classes, Server and Account. These are MarshalByRefObject objects. The Server application marshals the Server class as a singleton object.

客户端应用程序引用SharedTypes并通过iServer的接口成功连接到remoteable Server对象。在这里,我可以打电话和的getStatus CreateAccount(返回客户端激活的对象)成功。一切OK为止。

Client application references SharedTypes and connects to the remoteable Server object through the IServer interface successfully. Here I can call GetStatus and CreateAccount (which returns a client activated object) successfully. All OK so far.

现在我增加SharedTypes的版本为V2.0.0.0并注册到GAC,删除旧的V1.0.0.0版本。

Now I increment the version of SharedTypes to v2.0.0.0 and register into the GAC, removing the old v1.0.0.0 version.

服务器应用程序建立针对这个版本,但客户端是没有的。

The Server application is built against this version, but the client is not.

现在,当我运行客户端应用程序,它会如预期抱怨与System.IO.FileNotFoundException,也就是说,它无法找到在GAC SharedTypes的V1.0.0.0。

Now when I run the client application, it will as expected complain with a System.IO.FileNotFoundException, i.e. it could not find v1.0.0.0 of SharedTypes in the GAC.

如果我复制SharedTypes的V1.0.0.0客户端的exe文件目录,客户端应用程序最终绑定到这个(GAC后查找失败)。客户端应用程序启动,我可以调用的的getStatus iServer的对象上的成功(通过单独的对象)。但是,如果我叫CreateAccount - 这应该返回客户端激活的对象,我得到以下异常:

If I copy v1.0.0.0 of SharedTypes in the exe directory of the client, the client application eventually binds to this (after GAC lookup was unsuccessful). The client application starts and I can call the GetStatus on the IServer object successfully (through the singleton object). However, if I call CreateAccount – which should return a client activated object, I get the following exception:

System.InvalidCastException: Return argument has an invalid type.
   at System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object arg, Type paramType)
   at System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage msg, Object[] outArgs, Object returnValue)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at SharedTypes.IServer.GetAccount()

我的问题是,为什么不从客户端(这是使用V1.0.0.0)激活单对象的服务器不会抛出该异常调用上的getStatus,而创建客户端激活的对象,通过CreateAccount呢?由于这两种类型的服务器上创建的,我本来以为电话的getStatus将导致相同的异常?

My question is why does calling GetStatus on the server activated singleton object from the client (which is using v1.0.0.0) not throw this exception, whereas creating the client activated object through CreateAccount does? Since both types are created on the server, I would have thought that GetStatus call would have resulted in the same exception?

推荐答案

的CLR通常确保只有一个特定的组件的版本可装入一个过程。在这种情况下,因为有两个拷贝的CLR在工作中,一个服务器上,一个在客户端上不工作。所以,现在它是由远程处理基础设施,以确保远程访问类型的对象是兼容的。这是做的很到位,你的情况。不知道我提出在你的最后一句话的问题,但服务器不知道,否则在客户端加载的程序集的版本。

The CLR normally ensures that only one specific version of an assembly can be loaded into a process. That doesn't work in this scenario because there are two copies of the CLR at work, one on the server and one on the client. So now it is up to the remoting infrastructure to ensure that remoted type objects are compatible. Which is does with aplomb in your case. Not sure I got the question posed in your last sentence but the server is not otherwise aware of the version of the assembly loaded in the client.

重新编译客户端是必需的。

Recompiling the client is required.