У меня возникла проблема удаленного взаимодействия в моем приложении. Поскольку архитектура довольно сложная, я попытаюсь сделать простой пример с фиктивными именами, чтобы проиллюстрировать проблему.
Рассмотрим эти компоненты:
- MyApp.Client.exe: клиентское приложение
- MyApp.Service.exe: служба Windows, на которой размещен сервер
- MyApp.Server.dll: реализация сервера
- MyApp.Shared.dll: общая библиотека, содержащая общий интерфейс и определения типов
В MyApp.Shared.dll у меня есть эти интерфейсы:
public interface IFoo
{
...
}
public interface IFooManager
{
IList<IFoo> GetFooList();
...
}
Оба интерфейса реализованы в MyApp.Server.dll как MarshalByRefObjects
:
class Foo : MarshalByRefObject, IFoo
{
...
}
class FooManager : MarshalByRefObject, IFooManager
{
public IList<IFoo> GetFooList()
{
IList<IFoo> foos = new List<IFoo>();
// populate the list with instances of Foo
// ...
return foos;
}
...
}
На стороне клиента у меня есть экземпляр прокси для объекта FooManager
на сервере. Когда я вызываю GetFooList
для него, я вижу, что выполняется метод FooManager.GetFooList()
, но когда он возвращается, я получаю следующее SerializationException
:
Unable to find assembly 'MyApp.Server, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Server stack trace:
at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
at System.Runtime.Serialization.Formatters.Binary.ObjectMap.Create(String name, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Remoting.Channels.CoreChannel.DeserializeBinaryResponseMessage(Stream inputStream, IMethodCallMessage reqMsg, Boolean bStrictBinding)
at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.DeserializeMessage(IMethodCallMessage mcm, ITransportHeaders headers, Stream stream)
at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at MyApp.Shared.IFooManager.GetFooList()
...
at MyApp.Client.ViewModel.MainWindowViewModel.LoadFoos()
...
Так что я предполагаю, что он пытается сериализовать класс Foo
(я не получаю исключения, когда GetFooList
возвращает пустой список) или другой тип, используемый в Foo
. Но почему это попыталось бы сериализовать это? Поскольку Foo
является MarshalByRefObject
, разве он не должен возвращать прокси для экземпляра Foo
? И вообще, интерфейс IFoo
не предоставляет никаких объектов типов, определенных в MyApp.Server.dll ...
Проблема не возникала раньше, поскольку все сборки находились в одном каталоге, поэтому MyApp.Server.dll, вероятно, был загружен в клиентский домен приложений (чего не должно быть). Но сейчас я пытаюсь разделить клиентский и серверный компоненты, чтобы клиент не зависел от сборки на стороне сервера ...
Кто-нибудь имеет представление о том, что происходит? И как я могу получить более подробную информацию об исключении (например, какой тип он пытается сериализовать)? Трассировка стека не очень полезна ...