首页 > 解决方案 > 使用 Microsoft.CodeAnalysis.CSharp.Scripting 动态执行 C# 失败

问题描述

我需要以字符串格式执行 C# 类并使用该类的属性填充对象。为了达到要求,我正在做 POC,但失败了。

以下代码无法评估我尝试更新输入模型的位置。

程序.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();
        }
    }
}

脚本管理器.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;
        }
    }
}

模型.CS

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


标签: c#.net.net-corecsharpscript

解决方案


现在它起作用了:

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;
        }
    }
}

你有几个错误:

  1. 不使用options(第二个参数)Execute
  2. ctor 中的额外括号
  3. ctor 不应该有结果类型(void
  4. input属性未初始化
  5. 创建类和使用它的脚本是分开的

推荐阅读