namespace Testpad {
public class Program {
private static void Main(string[] args) {
HostContainer host = new HostContainer();
host.Run();
}
}
public interface IScript {
void SetHost(HostContainer host);
void HandleTick();
void EmitStopRequest();
}
public class HostContainer {
Timer timer = new Timer();
IScript script;
bool isRunning = true;
public void Run() {
string scriptCode = GetScript();
string extraNS = Assembly.GetCallingAssembly().Location;
string scriptAssembly = CSScript.CompileCode(scriptCode, null, true, new string[] { extraNS });
var helper = new AsmHelper(scriptAssembly, null, true);
this.script = helper.CreateAndAlignToInterface<IScript>("*");
this.script.SetHost(this);
this.timer.Tick += new EventHandler(timer_Tick);
this.timer.Interval = 100;
this.timer.Start();
while (isRunning) {
System.Threading.Thread.Sleep(100);
}
}
private void timer_Tick(object sender, EventArgs e) {
script.HandleTick();
}
public void HandleStopRequest() {
this.isRunning = false;
}
public void LogMessage(string msg) {
// Write msg to text box
}
private string GetScript() {
return @"
using System;
public class Script : MarshalByRefObject {
HostContainer host{ get; set; }
long counter = 0;
public void SetHost(Host host){
this.host = host;
}
public void HandleTick(){
this.host.LogMessage(@""script tick"");
counter++;
if (counter > 100)
this.host.HandleStopRequest();
}
}";
}
}
}
namespace Testpad {
public class ProgramHost {
private static void Main(string[] args) {
HostContainer hostContainer = new HostContainer();
hostContainer.Initialize();
Thread thread = new Thread(hostContainer.Run);
thread.Start();
Console.Out.WriteLine("Press any key to stop the execution ...");
Console.ReadKey();
thread.Abort();
hostContainer.Terminate();
}
}
public interface IScript {
void SetHost(HostContainer host);
void HandleTick(DateTime time);
void EmitStopRequest();
}
[Serializable]
public class HostContainer {
System.Threading.TimerCallback callback;
System.Threading.Timer timer;
IScript script;
[NonSerialized]
AsmHelper asmHelper;
public void Initialize() {
string scriptCode = GetScript();
string scriptAssembly = CSScript.CompileCode(scriptCode, null, true);
this.asmHelper = new AsmHelper(scriptAssembly, null, true);
this.script = this.asmHelper.CreateAndAlignToInterface<IScript>("*");
this.script.SetHost(this);
}
public void Run() {
this.callback = new TimerCallback(timer_Tick);
this.timer = new System.Threading.Timer(callback, null, 1000, 1000);
}
public void Terminate() {
this.asmHelper.Dispose();
}
private void timer_Tick(object state) {
script.HandleTick(DateTime.Now);
}
public void HandleStopRequest() {
this.timer = null;
}
public void LogMessage(string msg) {
Console.WriteLine(msg);
}
private string GetScript() {
return @"
using System;
using Testpad;
public class Script : MarshalByRefObject {
HostContainer host{ get; set; }
long counter = 0;
public void SetHost(HostContainer host){
this.host = host;
}
public void HandleTick(DateTime time){
this.host.LogMessage(string.Format(@""{0:HH:mm:ss.fff} Script tick"", time));
counter++;
if (counter > 3)
this.EmitStopRequest();
}
public void EmitStopRequest(){
this.host.LogMessage(@""Script done!"");
this.host.HandleStopRequest();
}
}";
}
}
}
Hi Dave,There are a few problems with your code.- In the script "SetHost" parameter declared as Host, which does not exist. It has to be HostContainer.- Your "using namespaces" in the script code missing Testpad namespace, which is required for the HostContainer type.- Your script does not implement "EmitStopRequest" so it cannot be aligned to the interface.- You timer is not firing Tick events. I do not know why.And there are a few potential improvements.- You do not need to pass the host assembly with "extraNS". By default the host and the script share the same set of laoded assemblies. Including the host assembly itself.- You do not need to "align" to interface. This technique is useful when the script has no knowledge about the host types and therefore you cannot use typecasting. However in your case the script is fully aware about the host and it can just inherit from IScript so you can use simple typecasting.- You instantiate AsmHelper in the way that implies further script unloading. However you do not dispose the AsmHelper instance, what suggests that you are not really concern about the script unloading. If it is indeed the case you do not need use AsmHelper at all and tehre is no need to inherit the script from MarshalByRefObject .If the proposed improvements are acceptable for your requirements then your script loading code can be as simple as follows:Host:this.script = (IScript)CSScript.LoadCode(scriptCode).CreateObject("*");this.script.SetHost(this);Script:using System;using Testpad;public class Script : IScript {HostContainer host{ get; set; }......You may also want to have a look at <cs-script>\Samples\Hosting folder containing hips of Hosting samples.Cheers,
Oleg Shilo
public void HandleStopRequest() {
this.timer = null;
}
Hi Dave,