In my last c# project, I need provide a special function, which is showing some menu items whose caption are not constant values. For example, an menu item's caption may be "Today(nov. 30)'s new blogs". The value "nov.30" will change to "Oct.1st" when the time goes.
So I developed a class(ExpressionEvaluator) to evaluate an expression like, "DateTime.Now.ToString()".
Here is my source code:
using System;
using Microsoft.VisualBasic.Vsa;
using Microsoft.Vsa;
using System.Reflection;
using System.Collections;
![](/Images/OutliningIndicators/None.gif)
namespace MyComanyName.Utils
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/ContractedBlock.gif)
{
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 提供表达式求值静态方法。
/// </summary>
public class ExpressionEvaluator
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](/Images/OutliningIndicators/ContractedSubBlock.gif)
nested class which implements IVsaSite#region nested class which implements IVsaSite
![](/Images/OutliningIndicators/InBlock.gif)
class VsaSite:IVsaSite
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
ArrayList _errors = new ArrayList();
public VsaSite()
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
![](/Images/OutliningIndicators/InBlock.gif)
public bool HasError
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return this._errors.Count>0;
}
}
![](/Images/OutliningIndicators/InBlock.gif)
public string Errors
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
string temp = "";
![](/Images/OutliningIndicators/InBlock.gif)
foreach(string str in _errors)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
temp += str;
}
![](/Images/OutliningIndicators/InBlock.gif)
return temp;
}
}
![](/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)
{
// TODO: 添加 ExpressionEvaluator.GetEventSourceInstance 实现
return null;
}
![](/Images/OutliningIndicators/InBlock.gif)
public object GetGlobalInstance(string name)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// TODO: 添加 ExpressionEvaluator.GetGlobalInstance 实现
return null;
}
![](/Images/OutliningIndicators/InBlock.gif)
public void Notify(string notify, object info)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// TODO: 添加 ExpressionEvaluator.Notify 实现
}
![](/Images/OutliningIndicators/InBlock.gif)
public bool OnCompilerError(IVsaError e)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
this._errors.Add(string.Format("Error of severity {0}: {2}", e.Severity, e.Description));
return false;
}
![](/Images/OutliningIndicators/InBlock.gif)
public void GetCompiledState(out byte[] pe, out byte[] debugInfo)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
// TODO: 添加 ExpressionEvaluator.GetCompiledState 实现
pe = null;
debugInfo = null;
}
![](/Images/OutliningIndicators/InBlock.gif)
#endregion
}
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
#endregion
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 求值
/// </summary>
/// <param name="str">表达式</param>
/// <returns>值</returns>
public static object Eval(string str)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
object result = null;
![](/Images/OutliningIndicators/InBlock.gif)
try
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
IVsaEngine _engine = new Microsoft.VisualBasic.Vsa.VsaEngine();
_engine.RootMoniker = "ExpressionScrip://eval/";
_engine.RootNamespace = "ExpressionScript";
_engine.Site = new VsaSite();
_engine.InitNew();
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
IVsaItems items = _engine.Items;
![](/Images/OutliningIndicators/InBlock.gif)
IVsaReferenceItem refItem;
![](/Images/OutliningIndicators/InBlock.gif)
// Add system.dll
refItem = (IVsaReferenceItem)items.CreateItem("system.dll",
VsaItemType.Reference,
VsaItemFlag.None);
refItem.AssemblyName = "system.dll";
![](/Images/OutliningIndicators/InBlock.gif)
// Add mscorlib.dll
refItem = (IVsaReferenceItem)items.CreateItem("mscorlib.dll",
VsaItemType.Reference,
VsaItemFlag.None);
refItem.AssemblyName = "mscorlib.dll";
![](/Images/OutliningIndicators/InBlock.gif)
IVsaCodeItem codeItem = (IVsaCodeItem)items.CreateItem("Script",VsaItemType.Code,VsaItemFlag.Class );
codeItem.SourceText = CreateClass(str);
![](/Images/OutliningIndicators/InBlock.gif)
if(_engine.Compile())
_engine.Run();
else
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
throw new EvaluateException("Compile error:"+ (_engine.Site as VsaSite).Errors);
}
![](/Images/OutliningIndicators/InBlock.gif)
// Execute the interface method. Using of ICloneable.Clone is just a trick.
Assembly assem = _engine.Assembly;
Type type = assem.GetType("ExpressionScript.Expression");
![](/Images/OutliningIndicators/InBlock.gif)
object o = Activator.CreateInstance(type);
![](/Images/OutliningIndicators/InBlock.gif)
if(o is ICloneable)
result = ( o as ICloneable).Clone();
![](/Images/OutliningIndicators/InBlock.gif)
_engine.Close();
}
catch(Exception ex)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
throw ex;
}
![](/Images/OutliningIndicators/InBlock.gif)
return result;
}
![](/Images/OutliningIndicators/InBlock.gif)
private static string CreateClass(string str)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return @"imports System
imports System.Windows.Forms
![](/Images/OutliningIndicators/InBlock.gif)
' The name of the module must match the name of the code item
' created in the hosting application via CreateItem.
Public Class Expression
Implements ICloneable
![](/Images/OutliningIndicators/InBlock.gif)
Public Overridable Function Clone() As Object Implements System.ICloneable.Clone
Return "+str+@"
End Function
End Class
";
}
}
![](/Images/OutliningIndicators/InBlock.gif)
public class EvaluateException:System.Exception
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
public EvaluateException(string msg):base(msg)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{}
![](/Images/OutliningIndicators/InBlock.gif)
public EvaluateException(string msg,System.Exception e):base(msg,e)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{}
}
}