Question

My current project is an application that allows you to write code in C# and then execute it using CSharpCodeProvider. It works fine at this point as long as the code is a complete application in itself, for example:

using System;

namespace RuntimeCode {
    public static class Program {
        public static void Main() {
            Console.WriteLine("Hello, world!");
        }
    }
}

The application then compiles the given code using CompileAssemblyFromSource with GenerateInMemory = true, and then invoking the Main method within the compiled assembly.

My question is, how can I let the compiled code access objects in the main application?

Was it helpful?

Solution 2

Your injected code can't access classes and objects defined in the main application.(to access classes defined in main application you can use reflection in the injected code again but the objects are inaccessible.)

But you can simply send data to injected code as a parameter:

using System;

namespace RuntimeCode {
    public static class Program {
        public static void StartPoint(object obj) {
            Console.WriteLine("Hello, world!");
        }
    }
}

Then invoke StartPoint method by sending obj object that contains the data it needs.

you can use any type of object you need. But it should be recognized by injected code.

OTHER TIPS

Note that runtime generated code is being executed as a separate process. Thus you need to perform a cross-process communication: between your main, host application and newly created.

A good way to implement cross-process or cross-domain commutation is to host a special service inside your main application or default app domain. And a resulting assembly will be a client.

I'd recommend to use WCF and NetNamedPipeBinding. You need just to configure contracts and endpoints.


Also note that the only thing GenerateInMemory=true controls is to load whether or not resulting assembly from disk to memory. That's it.


If you load your script into default AppDomain, that's a piece of cake even more. Just create a static member:

namespace MyNamespace
{
    public class Core
    {
        public static Core Instance { get; set; }
    }
}

and access it by full type name:

MyNamespace.Core.Instance;

The application then compiles the given code […], and then invoking the Main method within the compiled assembly.

I think that almost answers your question. There is no reason why the code you're compiling has to have a parameterless Main() method. For example, if the methods you need to access are in the IHost interface, then you could require your scripts to have a Main method with a parameter of type IHost. You would then invoke that, passing in the current instance of IHost.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top