Assembly CompileCode(string scriptText, string scriptFile, CompileInfo info) { Validate(info); // scriptFile is needed to allow injection of the debug information (byte[] asm, byte[] pdb) = Compile(scriptText, scriptFile, info); if (info?.PreferLoadingFromFile == true && info?.AssemblyFile.IsNotEmpty() == true) { // return Assembly.LoadFile(info.AssemblyFile); // this way the loaded script assembly can be referenced from // other scripts without custom asssembly probing return(Assembly.LoadFrom(info.AssemblyFile)); } else { if (pdb != null) { return(AppDomain.CurrentDomain.Load(asm, pdb)); } else { return(AppDomain.CurrentDomain.Load(asm)); } } }
/// <summary> /// Validates the specified information. /// </summary> /// <param name="info">The information.</param> /// <exception cref="CSScriptException">CompileInfo.RootClass property should only be used with Roslyn evaluator as " + /// "it addresses the limitation associated with Roslyn. Specifically wrapping ALL scripts in the illegally " + /// "named parent class. You are using CodeDomEvaluator so you should not set CompileInfo.RootClass to any custom value</exception> protected override void Validate(CompileInfo info) { if (info != null && info.RootClass != Globals.RootClassName) { throw new CSScriptException("CompileInfo.RootClass property should only be used with Roslyn evaluator as " + "it addresses the limitation associated with Roslyn. Specifically wrapping ALL scripts in the illegally " + "named parent class. You are using CodeDomEvaluator so you should not set CompileInfo.RootClass to any custom value"); } }
/// <summary> /// Compiles C# code (script) into assembly file. The C# code is a typical C# code containing a single or multiple class definition(s). /// </summary> /// <example> ///<code> /// string asmFile = CSScript.Evaluator /// .CompileAssemblyFromCode( /// @"using System; /// public class Script /// { /// public int Sum(int a, int b) /// { /// return a+b; /// } /// }", /// "MyScript.dll"); /// </code> /// </example> /// <param name="scriptText">The C# script text.</param> /// <param name="outputFile">The path to the assembly file to be compiled.</param> /// <returns>The compiled assembly file path.</returns> public string CompileAssemblyFromCode(string scriptText, string outputFile) { var info = new CompileInfo(); info.AssemblyFile = Path.GetFullPath(outputFile); info.PdbFile = Path.ChangeExtension(info.AssemblyFile, ".pdb"); Compile(scriptText, null, info); return(info.AssemblyFile); }
/// <summary> /// Compiles the specified script text. /// </summary> /// <param name="scriptText">The script text.</param> /// <param name="scriptFile">The script file.</param> /// <param name="info">The information.</param> /// <returns>The method result.</returns> override protected (byte[] asm, byte[] pdb) Compile(string scriptText, string scriptFile, CompileInfo info) { // Debug.Assert(false); string tempScriptFile = null; string injection_file = null; try { if (scriptFile == null) { tempScriptFile = CSScript.GetScriptTempFile(); File.WriteAllText(tempScriptFile, scriptText); } var project = Project.GenerateProjectFor(tempScriptFile ?? scriptFile); var refs = project.Refs.Concat(this.GetReferencedAssembliesFiles()).Distinct().ToArray(); var sources = project.Files; if (info?.AssemblyFile != null) { injection_file = CoreExtensions.GetScriptedCodeAttributeInjectionCode(info.AssemblyFile); sources = sources.Concat(new[] { injection_file }).ToArray(); } (byte[], byte[])result = CompileAssemblyFromFileBatch_with_Csc(sources, refs, info?.AssemblyFile, this.IsDebug, info); return(result); } finally { if (this.IsDebug) { CSScript.NoteTempFile(tempScriptFile); } else { tempScriptFile.FileDelete(rethrow: false); } injection_file.FileDelete(rethrow: false); CSScript.StartPurgingOldTempFiles(ignoreCurrentProcessScripts: true); } }
/// <summary> /// Validates the specified information. /// </summary> /// <param name="info">The information.</param> protected virtual void Validate(CompileInfo info) { }
/// <summary> /// Evaluates (compiles) C# code (script). The C# code is a typical C# code containing a single or multiple class definition(s). /// <para>The method is identical to <see cref="IEvaluator.CompileCode(string, CompileInfo)"/> except that it allows specifying /// the destination assembly file with <see cref="CompileInfo"/> object.</para> /// </summary> /// <example> /// <code> /// var info = new CompileInfo /// { /// AssemblyFile = @"E:\temp\asm.dll" /// }; /// /// Assembly asm = CSScript.Evaluator /// .Cast<RoslynEvaluator>() /// .CompileCode(@"using System; /// public class Script /// { /// public int Sum(int a, int b) /// { /// return a+b; /// } /// }", /// info); /// /// dynamic script = asm.CreateObject("*"); /// var result = script.Sum(7, 3); /// </code> /// </example> /// <param name="scriptText">The C# script text.</param> /// <param name="info"></param> /// <returns>The compiled assembly.</returns> public Assembly CompileCode(string scriptText, CompileInfo info = null) { return(CompileCode(scriptText, null, info)); }
/// <summary> /// Compiles the specified script text. /// </summary> /// <param name="scriptText">The script text.</param> /// <param name="scriptFile">The script file.</param> /// <param name="info">The information.</param> /// <returns>The method result.</returns> override protected (byte[] asm, byte[] pdb) Compile(string scriptText, string scriptFile, CompileInfo info) { string tempScriptFile = null; string injection_file = null; try { if (scriptFile == null) { tempScriptFile = CSScript.GetScriptTempFile(); File.WriteAllText(tempScriptFile, scriptText); } var project = Project.GenerateProjectFor(tempScriptFile ?? scriptFile); var refs = project.Refs.Concat(this.GetReferencedAssembliesFiles()).Distinct().ToArray(); var sources = project.Files; if (info?.AssemblyFile != null) { injection_file = CoreExtensions.GetScriptedCodeAttributeInjectionCode(info.AssemblyFile); sources = sources.Concat(new[] { injection_file }).ToArray(); } int scriptHash = 0; if (IsCachingEnabled) { var hashableCode = new StringBuilder(); hashableCode.Append($"{scriptText}.{scriptFile?.GetFullPath()}"); foreach (string dependencyScript in sources) { hashableCode.Append(File.ReadAllText(dependencyScript).GetHashCode()); } scriptHash = $"{scriptText}.{scriptFile?.GetFullPath()}".GetHashCode(); // not very sophisticated (e.g. not all ref asms are // included in hashing) // but adequate if (scriptCache.ContainsKey(scriptHash)) { return(scriptCache[scriptHash]); } } (byte[], byte[])result = CompileAssemblyFromFileBatch_with_Csc(sources, refs, info?.AssemblyFile, this.IsDebug, info); if (IsCachingEnabled) { scriptCache[scriptHash] = result; } return(result); } finally { if (this.IsDebug) { CSScript.NoteTempFile(tempScriptFile); } else { tempScriptFile.FileDelete(rethrow: false); } injection_file.FileDelete(rethrow: false); CSScript.StartPurgingOldTempFiles(ignoreCurrentProcessScripts: true); } }
/// <summary> /// Compiles the specified script text. /// </summary> /// <param name="scriptText">The script text.</param> /// <param name="scriptFile">The script file.</param> /// <param name="info">The information.</param> /// <returns>The method result.</returns> /// <exception cref="NotImplementedException"></exception> protected virtual (byte[] asm, byte[] pdb) Compile(string scriptText, string scriptFile, CompileInfo info) { throw new NotImplementedException(); }