System.InvalidCastException при создании клиентского активированного объекта с использованием более старой версии интерфейса, определенного в сборке со строгим именем - PullRequest
1 голос
/ 12 августа 2011

У меня есть вопрос о .Net Remoting, управлении версиями и создании активированных клиентом объектов.

Вот сценарий:

Есть 2 интерфейса, находящихся в их собственной сборке «SharedTypes»: IServer и IAccount. IServer содержит методы «GetStatus», который возвращает строку, и «CreateAccount», который возвращает тип IAccount. Это зарегистрировано в GAC как v1.0.0.0.

Приложение сервера ссылается на SharedTypes и реализует IServer и IAccount с конкретными классами, сервером и учетной записью. Это объекты MarshalByRefObject. Приложение Server маршализирует класс Server как одноэлементный объект.

Клиентское приложение ссылается на SharedTypes и успешно подключается к удаленному объекту Server через интерфейс IServer. Здесь я могу успешно вызвать GetStatus и CreateAccount (который возвращает активированный клиентом объект). Пока все в порядке.

Теперь я увеличиваю версию SharedTypes до v2.0.0.0 и регистрируюсь в GAC, удаляя старую версию v1.0.0.0.

Приложение сервера построено для этой версии, а клиент - нет.

Теперь, когда я запускаю клиентское приложение, оно, как и ожидалось, будет жаловаться на System.IO.FileNotFoundException, т. Е. Ему не удалось найти v1.0.0.0 SharedTypes в GAC.

Если я скопирую v1.0.0.0 SharedTypes в каталог exe клиента, клиентское приложение в конечном итоге будет привязано к этому (после того, как поиск в GAC оказался неудачным). Клиентское приложение запускается, и я могу успешно вызвать GetStatus для объекта IServer (через объект singleton). Однако, если я вызываю CreateAccount, который должен возвращать активированный клиентом объект, я получаю следующее исключение:

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()

Мой вопрос заключается в том, почему вызов GetStatus на активированном на сервере одноэлементном объекте с клиента (который использует v1.0.0.0) не вызывает это исключение, в то время как создание активированного клиентом объекта через CreateAccount делает это? Поскольку оба типа создаются на сервере, я бы подумал, что вызов GetStatus приведет к тому же исключению?

Ответы [ 3 ]

1 голос
/ 24 июня 2015

Это может не ответить на ваш конкретный вопрос, но ваш единственный вопрос, который я могу найти в StackOverflow относительно необъяснимого исключения InvalidCastException с сообщением «Аргумент возврата имеет недопустимый тип» с участием одноэлементного сервера.

В моемВ этом случае мой клиент начал с запроса синглтона сервера (т. е. объекта, который был передан RemotingServices.Marshal () на сервере), а затем в процессе его обработки получило ссылку на этот объект.синглтон с помощью других методов, и получил это исключение.

Я обошел его, создав два удаленных прокси для объекта верхнего уровня, один для использования в качестве одноэлементного, а другой для внутреннего использования в других контекстах.,Возможно, это связано с тем, что в ходе обработки клиента он пытался получить ссылку на этот одноэлементный объект через тип, отличный от того, который был передан в RemotingServices.Marshal () .Я все еще не уверен.Но наличие двух удаленных прокси-серверов для одного и того же локального объекта, одно из которых служило синглтоном удаленного взаимодействия, а другое для всех других внутренних целей, обошло проблему.К счастью, у меня есть архитектура удаленного прокси без сохранения состояния, поэтому наличие двух для одного и того же локального объекта не доставило никаких проблем.

Редактирование: Позже я нашел более простое решение, которое не требует двух прокси- вызовите RemotingServices.Marshal () с фактическим типом прокси в параметре 3 вместо типа интерфейса.

1 голос
/ 12 августа 2011

CLR обычно гарантирует, что в процесс может быть загружена только одна конкретная версия сборки.Это не работает в этом сценарии, потому что есть две копии CLR в работе, одна на сервере и одна на клиенте.Поэтому теперь все зависит от инфраструктуры удаленного взаимодействия, чтобы гарантировать совместимость объектов удаленного типа.Что делает с апломбом в вашем случае.Не уверен, что я получил вопрос, заданный в вашем последнем предложении, но сервер иначе не знает о версии сборки, загруженной в клиент.

0 голосов
/ 17 августа 2015

Для меня клиентское приложение было на .net 4.0, а серверное приложение работало на 4.5. Установка .net Framework 4.5 на клиентском компьютере исправила эту проблему.

...