forked from scriptcs/scriptcs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRoslynScriptEngine.cs
More file actions
128 lines (105 loc) · 4.58 KB
/
RoslynScriptEngine.cs
File metadata and controls
128 lines (105 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
using System.Collections.Generic;
using System.Linq;
using Common.Logging;
using Roslyn.Scripting;
using Roslyn.Scripting.CSharp;
using ScriptCs.Contracts;
namespace ScriptCs.Engine.Roslyn
{
using System.Runtime.ExceptionServices;
public class RoslynScriptEngine : IScriptEngine
{
protected readonly ScriptEngine ScriptEngine;
private readonly IScriptHostFactory _scriptHostFactory;
public const string SessionKey = "Session";
public RoslynScriptEngine(IScriptHostFactory scriptHostFactory, ILog logger)
{
ScriptEngine = new ScriptEngine();
ScriptEngine.AddReference(typeof(ScriptExecutor).Assembly);
_scriptHostFactory = scriptHostFactory;
Logger = logger;
}
protected ILog Logger { get; private set; }
public string BaseDirectory
{
get { return ScriptEngine.BaseDirectory; }
set { ScriptEngine.BaseDirectory = value; }
}
public string CacheDirectory { get; set; }
public string FileName { get; set; }
public ScriptResult Execute(string code, string[] scriptArgs, IEnumerable<string> references, IEnumerable<string> namespaces, ScriptPackSession scriptPackSession)
{
Guard.AgainstNullArgument("scriptPackSession", scriptPackSession);
Logger.Debug("Starting to create execution components");
Logger.Debug("Creating script host");
var distinctReferences = references.Union(scriptPackSession.References).Distinct().ToList();
SessionState<Session> sessionState;
if (!scriptPackSession.State.ContainsKey(SessionKey))
{
var host = _scriptHostFactory.CreateScriptHost(new ScriptPackManager(scriptPackSession.Contexts), scriptArgs);
Logger.Debug("Creating session");
var hostType = host.GetType();
ScriptEngine.AddReference(hostType.Assembly);
var session = ScriptEngine.CreateSession(host, hostType);
foreach (var reference in distinctReferences)
{
Logger.DebugFormat("Adding reference to {0}", reference);
session.AddReference(reference);
}
foreach (var @namespace in namespaces.Union(scriptPackSession.Namespaces).Distinct())
{
Logger.DebugFormat("Importing namespace {0}", @namespace);
session.ImportNamespace(@namespace);
}
sessionState = new SessionState<Session> { References = distinctReferences, Session = session };
scriptPackSession.State[SessionKey] = sessionState;
}
else
{
Logger.Debug("Reusing existing session");
sessionState = (SessionState<Session>)scriptPackSession.State[SessionKey];
var newReferences = sessionState.References == null || !sessionState.References.Any() ? distinctReferences : distinctReferences.Except(sessionState.References);
if (newReferences.Any())
{
foreach (var reference in newReferences)
{
Logger.DebugFormat("Adding reference to {0}", reference);
sessionState.Session.AddReference(reference);
}
sessionState.References = newReferences;
}
}
Logger.Debug("Starting execution");
var result = Execute(code, sessionState.Session);
Logger.Debug("Finished execution");
return result;
}
protected virtual ScriptResult Execute(string code, Session session)
{
Guard.AgainstNullArgument("session", session);
var result = new ScriptResult();
try
{
var submission = session.CompileSubmission<object>(code);
try
{
result.ReturnValue = submission.Execute();
}
catch (Exception ex)
{
result.ExecuteExceptionInfo = ExceptionDispatchInfo.Capture(ex);
}
}
catch (Exception ex)
{
result.UpdateClosingExpectation(ex);
if (!result.IsPendingClosingChar)
{
result.CompileExceptionInfo = ExceptionDispatchInfo.Capture(ex);
}
}
return result;
}
}
}