Dynamically Execute C# with Microsoft.CodeAnalysis.CSharp.Scripting is failing

2.3k views Asked by At

I have a requirement of executing a C# class in the string format and populate an object with the properties of that class. To achieve the requirement I was doing a POC and that's failed.

Following code is failing to evaluate where i was trying to update the input model.

Program.cs

using Microsoft.CodeAnalysis.CSharp.Scripting;
using System;

namespace CSCodeExecuter
{
    class Program
    {
        static void Main(string[] args)
        {
            Model input = new Model();
            string scriptId = "123";
            ScriptManager sriptMgr = new ScriptManager();
            sriptMgr.ExecuteScript<Model>(scriptId, ref input);

            Console.WriteLine(input.ToString());
            Console.ReadKey();
        }
    }
}

ScriptManager.cs

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSCodeExecuter
{
    public class ScriptManager
    {
        public void ExecuteScript<T>(string scriptId, ref T input)
        {
            try
            {
                string inputSript = GetStriptById(scriptId);
                var scriptOptions = ScriptOptions.Default;
                scriptOptions.AddReferences("CSCodeExecuter");
                
                Execute(inputSript, scriptOptions);
                var result = Execute("new ScriptedClass().input", scriptOptions);
            }
            catch (Exception ex)
            {
                throw;
            }
            
        }

        private string GetStriptById(string id)
        {
  
            string csSript = @" public class ScriptedClass
            {
                public CSCodeExecuter.Model input {get;set;}
                public void ScriptedClass()
                {
                   {" + GetInternalScript() + @"}
                }
            }";

            return csSript;
        }

        private string GetInternalScript()
        {
            return "input.Id = \"1111\"; " + "input.Name = \"test\"; " + "input.Phone = \"1234567890\"; ";
        }


        private static ScriptState<object> scriptState = null;
        public static object Execute(string code, dynamic scriptOptions)
        {
            scriptState = scriptState == null ? CSharpScript.RunAsync(code).Result : scriptState.ContinueWithAsync(code).Result;

            if (scriptState.ReturnValue != null && !string.IsNullOrEmpty(scriptState.ReturnValue.ToString()))
                return scriptState.ReturnValue;
            return null;
        }
    }
}

Model.CS

namespace CSCodeExecuter
{
    public class Model
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string Phone { get; set; }
    }
}


1

There are 1 answers

0
EgoPingvina On BEST ANSWER

Now it works:

using System;

using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;

namespace CSCodeExecuter
{
    public class ScriptManager
    {
        public void ExecuteScript<T>(string scriptId, ref T input)
        {
            try
            {
                string inputSript = GetStriptById(scriptId);
                var scriptOptions = ScriptOptions.Default.AddReferences("CSCodeExecuter");

                var result = Execute(inputSript, scriptOptions);
            }
            catch (Exception ex)
            {
                throw;
            }

        }

        private string GetStriptById(string id)
        {

            string csSript =
                @"
                public class ScriptedClass
                {
                    public CSCodeExecuter.Model input {get;set;}
                    public ScriptedClass()
                    {
                        " + GetInternalScript() + @"
                    }
                }

                return (new ScriptedClass()).input;";

            return csSript;
        }

        private string GetInternalScript()
        {
            return "input = new CSCodeExecuter.Model(); input.Id = \"1111\"; input.Name = \"test\"; input.Phone = \"1234567890\"; ";
        }


        private static ScriptState<object> scriptState = null;
        public static object Execute(string code, dynamic scriptOptions)
        {
            scriptState = scriptState == null ? CSharpScript.RunAsync(code, scriptOptions).Result : scriptState.ContinueWithAsync(code).Result;

            if (scriptState.ReturnValue != null && !string.IsNullOrEmpty(scriptState.ReturnValue.ToString()))
                return scriptState.ReturnValue;
            return null;
        }
    }
}

You had several errors:

  1. not use options(second parameter) in Execute
  2. extra parentheses in ctor
  3. ctor should not has a result type(void)
  4. input property was not initialized
  5. scripts with creating of class and using of it was separated