views:

59

answers:

3

Hi everyone!

I wanted to transfer (and execute) an Action or Func object from a C# client to a C# server application using WCF.

Here's my 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!");
        });
    }
}

When executing the line "server.Execute" I get a CommunicationException. Does anyone know how to fix this error?

Thanks for your help!

A: 

http://stackoverflow.com/questions/2386227/i-want-to-be-able-to-use-a-lambda-expression-to-specify-a-range-of-values-to-retu

is a similar question i asked.

I link you too it as eric lippert showed how such a solution would be possible.

However its a decent amount of work.

John Nicholas
+1  A: 

I would think of two solutions, both being pretty crazy in their nature. Mainly because your request of sending code to server for execution is nothing people do every day (and I think noone ever did something like that).

  1. DLL solution: Compile your code into separate DLL. Send this DLL as stream to server. Load some class with interface using reflection on server from this DLL. Then you can run code in created class.

  2. Code solution: Basicaly same as first one, but instead of sending precompiled DLL, you just send your code as string and then use programatic C# compiler to compile and run that code.

But you still cant extract your code from any function. And remember Action is nothing more than delegate (reference) for hard-coded function in your assembly.

Euphoric
So you also think what I want to do is NOT POSSIBLE in the way I showed or don't you no HOW to do it this way. Compiling to DLL or something like this isn't an option for me.
youllknow
Like I said. Action or Func is not an object, it is reference to function. Just think of Action as function. Can you send function to server for execution? No you cant. At least not in way you think you can.
Euphoric
So you basically a function is not an "real" object?
youllknow
Shouldn't everything be an object in C#!?
youllknow
All things can be represented as objects (see your Action). But there is only little, general object is able to do(bascaly nothing). In your case you need your object to implement ISerialisable (or something similiar) so it can be turned into text-friendly form, sent over network and then reconstucted back into object. Functions dont have such ability. Mainly because they are integral part of your executable and cannot be extracted easily from it.
Euphoric
Thanks, very good explaination!
youllknow
A: 

There may be existing solutions out there, I know not. (There are some pretty nifty run-time byte-code injection/manipulation tools available, so...)

But given sufficient permissions (and level of trust! -- that's a big one) one can compile-on-the-fly and/or send various self-evaluation expressions across the network (this is different than sending byte-code, per-se, although that could theoretically be done if the byte-code or an equivalent can be extracted).

The approaches above wouldn't be sending an Action<...>, which would require byte-code extraction for serialization (including capturing the context, if any), but rather something like Compiling C# on the Fly which you can follow to an interesting discussion and finally find CodeDOM.

On the other hand, LINQ "gets about" the issue of byte-code extraction/de-compilation with the use of Expression trees. Note that it doesn't send over byte-code, but rather uses this method to allow remote execution of expression trees (a common one being an SQL query).

pst