Use Script# to compile code (stand-alone)

╄→尐↘猪︶ㄣ 提交于 2020-01-13 19:30:34

问题


I'm trying to compile small fragments of C# into JavaScript using the Script# compiler.

But I don't get anything in return, GetStream() in my MemoryStreamSource is not even being called, so I must be doing something wrong.

Here's my code:

CodeScriptCompiler csc = new CodeScriptCompiler();

return csc.CompileCSharp("String.IsNullOrWhiteSpace(Model.MobilePhoneNumber)");

CodeScriptCompiler.cs

using System;
using System.Collections.Generic;
using ScriptSharp;

namespace CodeToScriptCompiler
{
    public class CodeScriptCompiler
    {
        ScriptCompiler sc = new ScriptCompiler();

        public string CompileCSharp(string csharpCode)
        {
            string errorMessages = String.Empty;

            CompilerOptions options = new CompilerOptions();
            options.Defines = new List<string>();
            options.References = new List<string>();
            options.References.Add("System.dll");
            options.Resources = new List<IStreamSource>();
            options.Sources = new List<IStreamSource>();
            options.Sources.Add(new MemoryStreamSource(csharpCode));
            options.TemplateFile = new MemoryStreamSource(csharpCode);

            MemoryStreamDestination output = new MemoryStreamDestination();
            options.ScriptFile = output;

            if (!options.Validate(out errorMessages))
            {
                return errorMessages;
            }

            return output.GetCompiledCode();
        }
    }
}

MemoryStreamSource.cs

using System.IO;
using System.Text;
using ScriptSharp;

namespace CodeToScriptCompiler
{
    public class MemoryStreamSource : IStreamSource
    {
        private string _code;

        private MemoryStream _memoryStream;

        public MemoryStreamSource(string code)
        {
            this._code = code;
        }

        public string Name
        {
            get { return "InMemoryCode"; }
        }

        public string FullName
        {
            get { return "InMemoryCode"; }
        }

        public void CloseStream(Stream stream)
        {
            stream.Close();
        }

        public Stream GetStream()
        {
            this._memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(this._code));

            return this._memoryStream;
        }
    }
}

MemoryStreamDestination.cs

using System;
using System.IO;
using ScriptSharp;

namespace CodeToScriptCompiler
{
    public class MemoryStreamDestination : IStreamSource
    {
        private MemoryStream _memoryStream;

        private string _compiledCode;

        public string Name
        {
            get { return "MemoryStreamDestination"; }
        }

        public string FullName
        {
            get { return "MemoryStreamDestination"; }
        }

        public void CloseStream(Stream stream)
        {
            if (String.IsNullOrWhiteSpace(this._compiledCode))
            {
                this._compiledCode = this.GetCompiledCode();
            }

            stream.Close();
        }

        public Stream GetStream()
        {
            this._memoryStream = new MemoryStream();

            return this._memoryStream;
        }

        public string GetCompiledCode()
        {
            if (!String.IsNullOrWhiteSpace(this._compiledCode))
            {
                return this._compiledCode;
            }

            if (this._memoryStream != null)
            {
                using (StreamReader sr = new StreamReader(this._memoryStream))
                {
                    return sr.ReadToEnd();
                }
            }

            return String.Empty;
        }
    }
}

回答1:


Some things I see potentially problematic.

  1. TemplateFile is set to a c# code stream. Leave it unset, since that is not a valid template.
  2. References should include the script# mscorlib, and furthermore, only full paths to valid script# assemblies. System.dll is not a script# assembly.
  3. Before you read from the MemoryStream, you need to set the stream position back to the start, otherwise it is at the end after the compiler has written to it, and there is nothing more to read.
  4. Not seeing a call to Compile on the Compiler instance you created, passing in the options instance. My guess is you did do that, just not there in the stack overflow snippet.

You probably should also implement IErrorHandler and pass that to the compiler to get error messages should they occur, once you have the basic thing working.

For reference you can also look at the unit tests at https://github.com/nikhilk/scriptsharp/tree/master/tests/ScriptSharp/Core which does something similar.

Note that you'll need a valid c# source file, rather than a single standalone expression. You can however likely deal with that by stripping off stuff from the start and end of the resulting script to get the script for just the expression you care about.

Hope that helps.

I am certainly interested/curious to understand how you're using this, and where you're compiling c# to script dynamically...



来源:https://stackoverflow.com/questions/12297223/use-script-to-compile-code-stand-alone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!