Script Packs allow you to bootstrap the environment for new scripts, further reducing the amount of code necessary to take advantage of your favorite C# frameworks. For more background on why Script Packs were created / needed, see [here] (http://codebetter.com/glennblock/2013/05/14/scripting-ease-with-script-packs/).
To use a Script Pack, install it from NuGet and use the scriptcs Require<T>
mechanism to import it into your script. E.g.
Create a folder: mkdir scriptpacks101
Navigate to the folder: cd scriptpacks101
Install the ScriptCs.Adder script pack: scriptcs -install ScriptCs.Adder
Create a script and save it as adder.csx
:
var adder = Require<Adder>();
var answer = adder.Add(1, 2);
Console.WriteLine(answer);
Execute your script: scriptcs adder.csx
IScriptPackContext
. This class should have methods which will surface to the consumer of the Script Pack in their script. Context classes should always be designed in a lazy fashion. This means that they should not do any work on construction. They should wait until the consumer accesses one of the members. This type will be what the consumer provides as T
to Require<T>()
to load the pack, so choose the name carefully. For example in the [Web API Script Pack] (https://github.com/scriptcs-contrib/scriptcs-webapi), the Context is called just WebApi
to allow the consumer to do Require<WebApi>()
. A common convention the community has adopted is to add the suffix Pack, i.e. ScriptCs.Nancy uses NancyPack
for the context.ScriptPack
that implements ScriptPack<T>
where T
is the context class. In the pack you can override the Initialize
method and add logic to add imports or assembly references. You do this by accessing the members of the provided IScriptPackSession
object. Don't worry about naming collisions, as the class will never be used directly by a consumer.ScriptCs.xxx
i.e. ScriptCs.Nancy
.scriptcs-xxx
as the name.Below you can see how to implement the simple Adder example shown earlier. In this case there are no using statements or references so the pack itself is empty.
public class Adder : IScriptPackContext { public int Add(int first, int second) { return first + second } } public class ScriptPack : ScriptPack<Adder> { }Adding imports and references.
The Web API Script Pack brings in additional assembly references and imports. Here is a snippet showing how it does this:
void IScriptPack.Initialize(IScriptPackSession session) { session.AddReference("System.Net.Http"); var namespaces = new[] { "System.Web.Http", "System.Web.Http.Routing", "System.Net.Http", "System.Net.Http.Headers", "Owin" }.ToList(); namespaces.ForEach(session.ImportNamespace); }
As you can see, it is adding an assembly reference to System.Net.Http
as well as importing common namespaces that will be needed by consumers. It is important that all namespaces for any types are exposed via the members of the Context class are added. For example, the Web API pack has a Configure
method which accepts an HttpConfiguration
param, thus the System.Web.Http
namespace must be added, or the consumer calling it will fail unless they have added their own using statement.
Script Packs are discovered and instantiated using [MEF] (http://msdn.microsoft.com/en-us/library/dd460648%28v=vs.110%29.aspx). The IScriptPack
interface which all packs implement is annotated with an [InheritedExport]
attribute making all packs MEF parts which export IScriptPack
This means that Script Packs can also import other contracts either from within the Script Pack or from other Script Packs. scriptcs also provides some common services that can also be injected. Beyond that, by injecting services you can make your packs easier to test, by allowing those services to be mockable.
To allow services to be injected, you use property or constructor injection. Constructor Injection is the most common / preferred way so that will be covered here.
IScriptPack
[ImportingConstructor]
attribute to that constructor.[ImportMany]
attribute if the param is a collection of imports otherwise no attribute is needed.[Export]
attribute, custom Export attribute, or that they implement an interface that is annotated with [InheritedExport]
The Web API Script Pack injects services in its constructor:
[ImportingConstructor] public ScriptPack(ILog logger, IControllerTypeManager typeManager) { _logger = logger; _typeManager = typeManager; }
ILog
is a logging service provided by the scriptcs host itself to allow writing to the scriptcs log infrastructure. IControllerTypeManager
however is a part that is exported within the script pack.
[Export(typeof(IControllerTypeManager))] public class ControllerTypeManager : IControllerTypeManager { ... }
Though in this example, the IControllerTypeManager
export is within the Script Pack itself, it does not have to be. You can have parts provided in extension NuGet packages which are installed along with the pack they are extending. scriptcs will automatically discover them and make them available as exports.
For the list of script packs, see the Script Packs master list.
For more information about authoring script packs, also see Authoring-script-packs.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4