Sharing runtime assembly in C# Roslyn script

20 Views Asked by At

I have maybe a bit of a unique setup here. I am hosting am embedded .net runtime in a c++ app using nethost.h and loading my assembly and getting fn pointers with load_assembly_and_get_function_pointer. It's invoking everything fine. In the function I'm calling on the .net side I am using Roslyn to run .csx scripts.

In that .net lib I define an interface INpcEvent and in the .csx I create a class that implements that interface and returns a new instance. I want to be able to get a reference to that new instance via this code:

var scriptOptions = ScriptOptions.Default.WithReferences(MetadataReference.CreateFromFile($"{directory}/DotNetTypes.dll")); // This is already referenced in this running assembly as a dependency
var state = await CSharpScript.RunAsync<GlobalType.INpcEvent>(text, scriptOptions, globals: global, globalsType: typeof(GlobalType));

And I get the error Exception thrown: 'System.ArgumentException' in System.Private.CoreLib.dll: 'Cannot bind to the target method because its signature is not compatible with that of the delegate type.'`

I did some debugging and found that there were two separate assemblies loaded, although they are both pointing to the same assembly on disk (DotNetType.dll).

I was able to get things "working" by defining factory methods with serializable types to create the arguments I needed like the following

var scriptOptions = ScriptOptions.Default.WithReferences(MetadataReference.CreateFromFile($"{directory}/DotNetTypes.dll"));
    var state = await CSharpScript.RunAsync<object>(text, scriptOptions);
    NpcMap[npcName] = state.ReturnValue;
    var instance = NpcMap[npcName];
    var createNpcEvent = instance.GetType()?.BaseType?.Assembly.ExportedTypes.FirstOrDefault(f => f.FullName == "EqFactory")?.GetMethod("CreateNpcEvent");
    if (createNpcEvent != null)
    {
        var npcEvent = createNpcEvent.Invoke(instance, [initArgs?.Zone, initArgs?.EntityList, npcEventArgs.Npc, npcEventArgs.Mob, message ?? ""]);
        var methodInfo = instance.GetType().GetMethod(MethodMap[id]);
        if (methodInfo != null)
        {
            methodInfo.Invoke(instance, [npcEvent]);
        }
    }

But I'd really like to be able to reuse the same assembly in runtime. Is there something I'm missing or another alternative to Roslyn to be able to achieve this?

0

There are 0 best solutions below