小马

现在是零将来是无限

导航

Expression Evaluator

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;

namespace MyComanyName.Utils
{
    
/// <summary>
    
/// 提供表达式求值静态方法。
    
/// </summary>

    public class ExpressionEvaluator
    
{
        
nested class which implements IVsaSite

        
/// <summary>
        
/// 求值
        
/// </summary>
        
/// <param name="str">表达式</param>
        
/// <returns></returns>

        public static object Eval(string str)
        
{
            
object result = null;

            
try
            
{
                IVsaEngine _engine 
= new Microsoft.VisualBasic.Vsa.VsaEngine();
            
                _engine.RootMoniker 
= "ExpressionScrip://eval/";
                _engine.RootNamespace 
= "ExpressionScript";                
                _engine.Site 
= new VsaSite();
                _engine.InitNew();


                IVsaItems items 
= _engine.Items;

                IVsaReferenceItem   refItem;

                
// Add system.dll
                refItem = (IVsaReferenceItem)items.CreateItem("system.dll",
                    VsaItemType.Reference,
                    VsaItemFlag.None);
                refItem.AssemblyName 
= "system.dll";

                
// Add mscorlib.dll
                refItem = (IVsaReferenceItem)items.CreateItem("mscorlib.dll",
                    VsaItemType.Reference,
                    VsaItemFlag.None);
                refItem.AssemblyName 
= "mscorlib.dll";

                IVsaCodeItem codeItem 
= (IVsaCodeItem)items.CreateItem("Script",VsaItemType.Code,VsaItemFlag.Class );
                codeItem.SourceText 
= CreateClass(str);

                
if(_engine.Compile())
                    _engine.Run();
                
else
                
{
                    
throw new EvaluateException("Compile error:"+ (_engine.Site  as VsaSite).Errors);
                }


                
// Execute the interface method. Using of ICloneable.Clone is just a trick.
                Assembly   assem = _engine.Assembly;
                Type       type 
= assem.GetType("ExpressionScript.Expression");

                
object o = Activator.CreateInstance(type);

                
if(o is ICloneable)
                    result 
= ( o as ICloneable).Clone();

                _engine.Close();
            }

            
catch(Exception ex)
            
{
                
throw ex;
            }


            
return result;
        }


        
private static string CreateClass(string str)
        
{
            
return @"imports System
                    imports System.Windows.Forms

                    
' 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

                        Public Overridable Function Clone() As Object Implements System.ICloneable.Clone
                            Return 
"+str+@"
                        End Function
                    End Class
                    
";
        }

    }


    
public class EvaluateException:System.Exception
    
{
        
public EvaluateException(string msg):base(msg)
        
{}

        
public EvaluateException(string msg,System.Exception e):base(msg,e)
        
{}
    }

}


 

posted on 2004-11-30 14:55  mahope  阅读(2403)  评论(3编辑  收藏  举报