expose #load and #r as services for script packs
adamralph opened this issue · 23 comments
As an enhancement to adamralph/scriptcs-nancy#12 instead of having to do:
> nancy.Start();
> #load "somemodules.csx"
> nancy.Refresh();
> #r "SomeMoreModules.dll"
> nancy.Add(typeof(CoolModule).Assembly);
I'd like to do:
> nancy.Start();
> nancy.Add("somemodules.csx");
> nancy.Add("SomeMoreModules.dll");
The script pack would take the script or assembly path and pass it back to the script engine which would effectively do either a #load
or #r
, passing back an Assembly
reference which the pack would use to find new modules.
Update 2013-06-13
The above use case isn't really so important now since automatic module finding is in place, so all I'd need to do is:-
> nancy.Go();
> #load "somemodules.csx"
> nancy.Go();
> #r "SomeMoreModules.dll"
> nancy.Go();
However, another feature I really want to build in is automatic loading of modules from the file system based on convention (adamralph/scriptcs-nancy#13) and I believe I need #load and #r as services for this.
You don't need to use #r for the dll, you just need the dll in the bin folder and it will automatically load.
-----Original Message-----
From: "Adam Ralph" notifications@github.com
Sent: 5/12/2013 5:58 AM
To: "scriptcs/scriptcs" scriptcs@noreply.github.com
Subject: [scriptcs] expose #load and #r as services for script packs (#243)
As an enhancement to adamralph/scriptcs-nancy#12 instead of having to do:
nancy.Start();
#load "somemodules.csx"
nancy.Refresh();
#r "SomeMoreModules.dll"
nancy.Add(typeof(CoolModule).Assembly);
I'd like to do:
nancy.Start();
nancy.Add("somemodules.csx");
nancy.Add("SomeMoreModules.dll");
The script pack would take the script or assembly path and pass it back to the script engine which would effectively do either a #load or reference #r, passing back an Assembly reference which the pack would use to find new modules.
As an aside, it would be great if scriptcs could expose a reference to the current script assembly. At the moment I have to do Assembly.GetCallingAssembly() but this ought to be abstracted away by scriptcs.
—
Reply to this email directly or view it on GitHub.
Yes but once the REPL is running, the only way to load a DLL into the existing session context is via #r
.
In that sense, it might be interesting to expose that as a service, so that script packs can orchestrate loading of new DLLs themselves when running in REPL mode.
Yeah, what @filipw said ;-). Also bear in mind that I want to implement adamralph/scriptcs-nancy#13
Oh this is for REPL? I missed that.
On Sun, May 12, 2013 at 11:06 AM, Adam Ralph notifications@github.comwrote:
Yeah, what @filipw https://github.com/filipw said ;-). Also bear in
mind that I want to implement adamralph/scriptcs-nancy#13adamralph/scriptcs-nancy#13—
Reply to this email directly or view it on GitHubhttps://github.com//issues/243#issuecomment-17782257
.
It is for REPL but also to allow me to do my own convention based location within a script pack.
@glennblock in reply to adamralph/scriptcs-nancy#13 (comment)
Ultimately what I need is, given a path to a script or assembly, I want to call something in scriptcs which does a #load
or #r
and then gives me back an Assembly
reference. If you require that I make the distinction between script and assembly then I can do, but I think it would be nice if scriptcs could do this itself. Perhaps that's something that could come later though.
Now, I haven't thought about the internal implementation at all ;-). I don't think I'm yet qualified to. I haven't really gotten deep and dirty with the scriptcs codebase yet.
@adamralph May not be possible what you are asking. We need to spike on it. It could be a chicken and egg problem. The dll doesn't exist yet, and once it does we're not sure you can load new scripts and not lose context. The REPL functionality relies on the fact that you definitely can bring new things into an existing session, but then you have a diff dll.
@adamralph I'll just stay quiet until we know more. We may be able to support this scenario but takes some investigation.
I am 99% sure we can get this working in the REPL no problem, as today each repl command is evaluating new code into the same session.
I am just not sure about the implications of doing this from within the middle of code that Roslyn is executing. But the more I think about it, I am thinking there should be a way, that is using the REPL as a reference point.
So I tried this:
> var x= 20;
> x
20
> #load "foo.csx"
> new Foo().Speak()
Foo speaks
> x
20
>
The value of x
persists. Does that imply this would work for #load
?
@adamralph we also have to make sure this could be supported in mono. We need @dragan to weigh in there.
@glennblock OK, I thought at bit more about what you are saying above and I get it now. You're concerned with the difference between scriptcs code doing stuff to the session DLL from oustide it vs the DLL doing the same thing to itself. This is all fascinating stuff 😉
@adamralph re: the code you posted - in REPL it works since session is persisted between executions of subsequent code lines.
In "normal" script execution you'd have the whole script compiled to an in memory assembly on startup, which poses a bit of a challenge - since having an dynamic inline load would mean you'd be trying to modify an existing assembly from within that assembly :-) Not saying that it's impossible though, we will try to come up with some ideas
Yes, it works in the REPL. If it did not that would be a pretty weak REPL :-) it works because we cache the Roslyn session and reuse it each time a line is compiled.
I am not sure however it will work if we compile into the season while code is executing. It might work though, have to test
-----Original Message-----
From: "Filip W" notifications@github.com
Sent: 5/12/2013 4:01 PM
To: "scriptcs/scriptcs" scriptcs@noreply.github.com
Cc: "Glenn Block" glenn.block@gmail.com
Subject: Re: [scriptcs] expose #load and #r as services for script packs(#243)
@adamralph re: the code you posted - in REPL it works since session is persisted between executions of subsequent code lines.
In "normal" script execution you'd have the whole script compiled to an in memory assembly on startup, which poses a bit of a challenge - since having an dynamic inline load would mean you'd be trying to modify an existing assembly from within that assembly :-) Not saying that it's impossible though, we will try to come up with some ideas
—
Reply to this email directly or view it on GitHub.
Thanks for putting effort into this one. If this works out it could make for a truly rails-like deployment scenario. I'm starting to envisage actually running production sites with this. I might never compile a line of C# again! ;-)
Very cool! Have you tried getting it to work with assemblies yet?
Nice one Filip!!!!
@filipw Is this still alive? I need a way of dynamically executing all scripts in a "scripts" folder, preferably at a time of my choosing.
Well it has been 3 years, but I started working on this with a diff approach, an Eval
function. Basically you call Eval
and it runs the code dynamically. It supports #load, etc and inherits the references from the parent / shares the same session.
Screenshot below
@filipw @PeteGoo @adamralph thoughts?
Been iterating on this more, and now the experience is more pythonic (thanks to a suggestion for @craignicol). You can create multiple sessions and reuse them. If you pass nothing, a new one will be created for you. If you want to allow access to the outer session, you use Env.Session
.