今天翻看.NET的类库,发现一个不知道的命名空间Microsoft.Vsa,于是找了找资料,才知道这个东西是为了给程序添加脚本支持。(当前只支持VB.NET,和JScript.NET),于是,试了试。
先要做一个引擎宿主,目的是把VSA(Visual Studio for Applicaiton)引擎调进来,然后执行脚本。
using System;
using Microsoft.Vsa;
using Microsoft.VisualBasic.Vsa;
![](/Images/OutliningIndicators/None.gif)
namespace VsaEngine
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
![](/Images/OutliningIndicators/InBlock.gif)
public class ScriptHost : Microsoft.Vsa.IVsaSite
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private byte[] code = new byte[1024];
![](/Images/OutliningIndicators/InBlock.gif)
private Microsoft.Vsa.IVsaEngine engine = null;
private Microsoft.Vsa.IVsaItems items = null;
![](/Images/OutliningIndicators/InBlock.gif)
public ScriptHost() // 设置vsa引擎的一些参数
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
engine = new Microsoft.VisualBasic.Vsa.VsaEngine();
engine.RootMoniker = "test://cnblogs.com/VsaEngine";
engine.Name = "VsaEngine";
engine.RootNamespace = "VsaEngine";
engine.Site = this;
items = engine.Items;
IVsaReferenceItem refItem = items.CreateItem("VsaEngine", Microsoft.Vsa.VsaItemType.Reference, VsaItemFlag.None) as IVsaReferenceItem;
refItem.AssemblyName = System.IO.Directory.GetCurrentDirectory() + "\VsaEngine.dll";
IVsaGlobalItem globalItem = items.CreateItem("HostObject", VsaItemType.AppGlobal, VsaItemFlag.None) as IVsaGlobalItem;
globalItem.TypeString = "VsaEngine.ScriptHost";
}
![](/Images/OutliningIndicators/InBlock.gif)
public bool SetScript(string scriptString) // 设置脚本,并进行语法检查
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
IVsaCodeItem codeItem = items.CreateItem("testCode", Microsoft.Vsa.VsaItemType.Code, Microsoft.Vsa.VsaItemFlag.Class) as IVsaCodeItem;
codeItem.SourceText = scriptString;
return engine.Compile();
}
![](/Images/OutliningIndicators/InBlock.gif)
public void Run() // 执行脚本
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
engine.Run();
}
![](/Images/OutliningIndicators/InBlock.gif)
private string _testMember = "Test";
public string TestMember // 用来测试的一个属性
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return _testMember;
}
set
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_testMember = value;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
public string GetResult() // 获取脚本执行结果
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
System.Type type = engine.Assembly.GetType("VsaEngine.myModule", true, true);
System.Reflection.MethodInfo[] mi = type.GetMethods();
System.Collections.IEnumerator enu = mi.GetEnumerator();
System.Reflection.MethodInfo method = type.GetMethod("myMethod");
object result = method.Invoke(this, null);
![](/Images/OutliningIndicators/InBlock.gif)
return result.ToString();
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
IVsaSite 成员#region IVsaSite 成员
![](/Images/OutliningIndicators/InBlock.gif)
public object GetEventSourceInstance(string itemName, string eventSourceName)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this;
}
![](/Images/OutliningIndicators/InBlock.gif)
public object GetGlobalInstance(string name)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this;
}
![](/Images/OutliningIndicators/InBlock.gif)
public void Notify(string notify, object info)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
![](/Images/OutliningIndicators/InBlock.gif)
public bool OnCompilerError(IVsaError error)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return false;
}
![](/Images/OutliningIndicators/InBlock.gif)
public void GetCompiledState(out byte[] pe, out byte[] debugInfo)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
pe = code;
debugInfo = null;
}
![](/Images/OutliningIndicators/InBlock.gif)
#endregion
}
}
然后就可以调用了
private void button1_Click(object sender, System.EventArgs e)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
System.Text.StringBuilder sbScript = new System.Text.StringBuilder();
sbScript.Append("Module myModule ");
sbScript.Append("Public Function myMethod As String ");
sbScript.Append("With HostObject ");
sbScript.Append(".TestMember="Hello World!" ");
sbScript.Append("End With ");
sbScript.Append("Return " OK" ");
sbScript.Append("End Function ");
sbScript.Append("End Module ");
![](/Images/OutliningIndicators/InBlock.gif)
ScriptHost host = new ScriptHost();
if(host.SetScript(sbScript.ToString()))
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
host.Run();
![](/Images/OutliningIndicators/InBlock.gif)
MessageBox.Show("VB script return value: " + host.GetResult() + " Local member value: " + host.TestMember);
}
else
MessageBox.Show("Compile Error");
}
还可以把VSA的IDE一起做进来,我还没做测试程序。
总的感觉还不错。除了给程序增加脚本支持外,还可以模拟BizTalk做工作流引擎的组件处理了![](/Emoticons/regular_smile.gif)