2010-10-16 15 views
1

Je voulais transférer (et exécuter) un objet Action ou Func d'un client C# vers une application serveur C# en utilisant WCF.Exécution à distance des objets Action <> ou Func <>

Voici mon code:

[ServiceContract] 
interface IRemoteExecuteServer 
{ 
    [OperationContract] 
    void Execute(Action action); 
} 

class RemoteExecuteServer : IRemoteExecuteServer 
{ 
    public void Execute(Action action) 
    { 
     action(); 
    } 
} 

Servercode:

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (ServiceHost host = new ServiceHost(typeof(RemoteExecuteServer), new Uri("net.tcp://localhost:8000"))) 
     { 
      host.AddServiceEndpoint(typeof(IRemoteExecuteServer), new NetTcpBinding(), "RES"); 
      host.Open(); 

      Console.WriteLine("Server is running!"); 
      Console.WriteLine("Press any key to exit..."); 
      Console.ReadKey(true); 

      host.Close(); 
     } 
    } 
} 

Clientcode:

class Program 
{ 
    static void Main(string[] args) 
    { 
     IRemoteExecuteServer server = new ChannelFactory<IRemoteExecuteServer>(new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:8000/RES")).CreateChannel(); 
     server.Execute(delegate() 
     { 
      Console.WriteLine("Hello server!"); 
     }); 
    } 
} 

Lors de l'exécution de la ligne "Server.Execute" Je reçois un CommunicationException. Est-ce que quelqu'un sait comment corriger cette erreur?

Merci pour votre aide!

Répondre

1

Je penserais à deux solutions, les deux étant assez fous dans leur nature. Principalement parce que votre demande d'envoyer du code au serveur pour exécution n'est rien que les gens font tous les jours (et je pense que personne n'a jamais fait quelque chose comme ça).

  1. solution DLL: compiler votre code dans la DLL séparée. Envoyer cette DLL en tant que flux sur le serveur. Chargez une classe avec l'interface en utilisant la réflexion sur le serveur à partir de cette DLL. Ensuite, vous pouvez exécuter du code dans la classe créée. Basiquement identique au premier, mais au lieu d'envoyer une DLL précompilée, vous envoyez simplement votre code sous forme de chaîne, puis utilisez le compilateur C# programmatique pour compiler et exécuter ce code.

Mais vous ne pouvez toujours pas extraire votre code de n'importe quelle fonction. Et rappelez-vous que Action n'est rien de plus qu'un délégué (référence) pour une fonction codée en dur dans votre assemblée.

+0

Donc, vous pensez aussi que ce que je veux faire n'est PAS POSSIBLE de la façon dont je l'ai montré ou n'est-ce pas vous qui le faites de cette façon. Compiler vers DLL ou quelque chose comme ça n'est pas une option pour moi. – raisyn

+0

Comme je l'ai dit. Action ou Func n'est pas un objet, c'est une référence à la fonction. Pensez simplement à Action en tant que fonction. Pouvez-vous envoyer la fonction au serveur pour l'exécution? Non, vous ne pouvez pas. Du moins pas de la façon dont tu penses pouvoir le faire. – Euphoric

+0

Donc vous fondamentalement une fonction n'est pas un objet "réel"? – raisyn

0

Il existe peut-être des solutions existantes, je ne sais pas. (Il existe de très jolis outils d'injection/manipulation de code d'exécution disponibles, donc ...)

Mais étant donné les permissions suffisantes (et le niveau de confiance - c'est un gros), on peut compiler-on- voler et/ou envoyer diverses expressions d'auto-évaluation sur le réseau (ceci est différent de l'envoi de byte-code, en soi, bien que cela puisse théoriquement être fait si le byte-code ou un équivalent peut être extrait). Les approches ci-dessus n'enverraient pas une Action < ...>, ce qui nécessiterait une extraction de code octet pour la sérialisation (y compris la capture du contexte, le cas échéant), mais plutôt quelque chose comme Compiling C# on the Fly que vous pouvez suivre jusqu'à discussion intéressante et enfin trouver CodeDOM. D'autre part, LINQ "se débarrasse" du problème de l'extraction/dé-compilation de code octet en utilisant Expression trees.Notez qu'il n'envoie pas de byte-code, mais qu'il utilise plutôt cette méthode pour permettre l'exécution à distance d'arborescences d'expression (une requête courante étant une requête SQL).