У меня есть приложение .NET, в котором сборки в отдельных AppDomains должны делить сериализованные объекты, которые передаются по значению.Как передать неизвестный тип между двумя .NET AppDomains?
Обе сборки ссылаются на общий узел, который определяет базовый класс для класса сервера, а также определяет базовый класс для типа entiy, который будет передан между доменами:
public abstract class ServerBase : MarshalByRefObject
{
public abstract EntityBase GetEntity();
}
[Serializable]
public abstract class EntityBase
{
}
Узел сервера определяет класс сервера и конкретная реализация типа объекта:
public class Server : ServerBase
{
public override EntityBase GetEntity()
{
return new EntityItem();
}
}
[Serializable]
public class EntityItem : EntityBase
{
}
Узел клиента создает AppDomain
, в котором сборка сервера будет организована и использует экземпляр класса сервера, чтобы запросить конкретный экземпляр типа объекта:
class Program
{
static void Main()
{
var domain = AppDomain.CreateDomain("Server");
var server = (ServerBase)Activator.CreateInstanceFrom(
domain,
@"..\..\..\Server\bin\Debug\Server.dll",
"Server.Server").Unwrap();
var entity = server.GetEntity();
}
}
Unfortnately, этот подход не с SerializationException
, потому что сборка клиент не имеет непосредственного знания конкретного типа, который возвращается.
Я читал, что удаленная работа .NET поддерживает неизвестные типы при использовании двоичной сериализации, но я не уверен, относится ли это к моей настройке или как ее настроить.
В качестве альтернативы, существует ли другой способ передачи неизвестного конкретного типа с сервера на клиент, учитывая, что клиенту требуется только доступ к нему через свой известный интерфейс базового класса.
Спасибо за ваши советы,
Tim
EDIT:
По просьбе Ганса, вот сообщение об исключении и трассировки стека.
SerializationException
Type is not resolved for member 'Server.EntityItem,Server, Version=1.0.0.0,Culture=neutral, PublicKeyToken=null'.
at Interop.ServerBase.GetEntity()
at Client.Program.Main() in C:\Users\Tim\Visual Studio .Net\Solutions\MEF Testbed\Client\Program.cs:line 12
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Спасибо Хансу. Ваше предложение очень разумно, но я должен быть уверен, что он не вводит дополнительную проблему. То, что я описал, является частью сценария песочницы, поэтому я не хочу, чтобы CLR загружал неизвестную сборку в основной AppDomain (который имеет более широкие разрешения), если это может поставить под угрозу безопасность. У вас есть мнение по этому поводу? Еще раз спасибо. –
Используйте интерфейс, объявленный в своей собственной сборке и ссылающийся на оба. –
ОК, я изменил класс EntityBase как интерфейс и по-прежнему находится в общей сборке, но исключение все еще бросается (и предположительно по той причине, что вы уже заявили), что переданный объект неизвестен клиент). –