J'ai une application .NET dans laquelle les assemblys dans des domaines d'application distincts doivent partager des objets sérialisés transmis par valeur.Comment passer un type inconnu entre deux .NET AppDomains?
Les deux ensembles font référence à un ensemble commun qui définit la classe de base de la classe de serveur et définit également la classe de base pour le type de entiy qui sera passé entre les domaines:
public abstract class ServerBase : MarshalByRefObject
{
public abstract EntityBase GetEntity();
}
[Serializable]
public abstract class EntityBase
{
}
Ensemble de serveur définit la classe de serveur et du béton Implémentation type d'entité:
public class Server : ServerBase
{
public override EntityBase GetEntity()
{
return new EntityItem();
}
}
[Serializable]
public class EntityItem : EntityBase
{
}
l'ensemble client crée le AppDomain
dans lequel l'ensemble du serveur sera hébergé et utilise une instance de la classe de serveur pour demander une instance concrète du type d'entité:
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, cette approche échoue avec un SerializationException
parce que l'ensemble client n'a pas connaissance directe du type de béton qui est retourné.
J'ai lu que .NET remoting prend en charge les types inconnus lors de l'utilisation de la sérialisation binaire, mais je ne suis pas sûr que cela s'applique à mon installation ou comment le configurer.
Alternativement, existe-t-il un autre moyen de transmettre un type de béton inconnu du serveur au client, étant donné que le client n'a besoin d'y accéder que via son interface de classe de base connue.
Merci pour vos conseils,
Tim
EDIT:
Comme demandé par Hans, voici le message d'exception et trace pile.
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()
Merci Hans. Votre suggestion est très raisonnable, mais je dois être sûr que cela n'introduit pas de problème supplémentaire. Ce que j'ai décrit fait partie d'un scénario de sandbox, donc je ne veux pas que le CLR charge l'assembly inconnu dans le domaine principal AppDomain (qui a des autorisations plus larges) s'il est susceptible de compromettre la sécurité. Avez-vous un point de vue à ce sujet? Merci encore. –
Utilisez une interface, déclarée dans son propre assembly et référencée par les deux. –
OK, j'ai changé la classe EntityBase en une interface et elle réside, comme précédemment, dans l'assembly partagé, mais l'exception est toujours levée (et vraisemblablement pour la raison que vous avez déjà indiquée) que l'objet passé est inconnu par le client). –