Skip to content

Commit

Permalink
Merge pull request #20 from bruce-dunwiddie/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
bruce-dunwiddie authored Sep 8, 2019
2 parents c26a7ea + c410460 commit 0d917bc
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 2 deletions.
31 changes: 31 additions & 0 deletions Data_Eval/Data_Eval/Compilation/CompilationException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,65 @@

namespace Data.Eval.Compilation
{
/// <summary>
/// Exception class that is raised if an error is thrown during compilation
/// step of Evaluator class containing additional information for troubleshooting.
/// </summary>
[Serializable]
public sealed class CompilationException : Exception
{
/// <summary>
/// Class code that was generated from Evaluator and attempted to be
/// compiled. Useful for troubleshooting compile error by seeing how
/// Evaluator used specified values when generating code for compilation.
/// </summary>
public string GeneratedClassCode { get; set; }

/// <summary>
///
/// </summary>
public CompilationException()
{

}

/// <summary>
///
/// </summary>
/// <param name="message"></param>
public CompilationException(string message)
: base(message)
{

}

/// <summary>
///
/// </summary>
/// <param name="message"></param>
/// <param name="innerException"></param>
public CompilationException(string message, Exception innerException)
: base(message, innerException)
{

}

/// <summary>
///
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
private CompilationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{

}

/// <summary>
///
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
Expand Down
2 changes: 1 addition & 1 deletion Data_Eval/Data_Eval/Data_Eval.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>Data_Eval.snk</AssemblyOriginatorKeyFile>
<Version>2.4.1</Version>
<Version>2.4.2</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
Expand Down
2 changes: 1 addition & 1 deletion Data_Eval/Data_Eval/Data_Eval.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<package>
<metadata>
<id>Data.Eval</id>
<version>2.4.1</version>
<version>2.4.2</version>
<title>Data.Eval</title>
<authors>Bruce Dunwiddie</authors>
<owners>shriop</owners>
Expand Down
122 changes: 122 additions & 0 deletions Data_Eval/Data_Eval/Evaluator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

namespace Data.Eval
{
/// <summary>
/// Class for evaluating and executing C# based string expressions
/// dynamically at runtime.
/// </summary>
public sealed class Evaluator
{
private readonly string expression;
Expand All @@ -23,12 +27,32 @@ public sealed class Evaluator

private static Dictionary<string, Execution> compiledTypes = new Dictionary<string, Execution>();

/// <summary>
/// Creates an instance of the evaluator by specifying the expression
/// to be evaluated.
/// </summary>
/// <param name="expression">
/// C# based string expression to be evaluated or executed, e.g.
/// "return 1+1" for evaluation or
/// "System.Console.WriteLine(\"Hello World!\")" for execution.
/// </param>
public Evaluator(
string expression)
{
this.expression = expression;
}

/// <summary>
/// Sets the value of a variable referenced within the expression prior
/// to evaluation or returns the value of a variable referenced within the
/// expression after evaluation.
/// </summary>
/// <param name="name">
/// Name of the variable referenced within the expression.
/// </param>
/// <returns>
/// Value of the variable referenced within the expression after evaluation.
/// </returns>
public object this[string name]
{
get
Expand All @@ -44,6 +68,16 @@ public object this[string name]
}
}

/// <summary>
/// Sets the value of a variable referenced within the expression prior
/// to evaluation.
/// </summary>
/// <param name="name">
/// Name of the variable referenced within the expression.
/// </param>
/// <param name="value">
/// Value of the variable that should be used when evaluating the expression.
/// </param>
public void SetVariable(
string name,
object value)
Expand All @@ -64,30 +98,73 @@ public void SetVariable(
}
}

/// <summary>
/// Returns the value of a variable referenced within the
/// expression after evaluation.
/// </summary>
/// <param name="name">
/// Name of the variable referenced within the expression.
/// </param>
/// <returns>
/// Value of the variable referenced within the expression after evaluation.
/// </returns>
public object GetVariable(
string name)
{
return variables[name].Value;
}

/// <summary>
/// Allows methods and types from an external library to be referenced
/// within an expression by providing the path to the location of the
/// assembly where they're defined.
/// </summary>
/// <param name="assemblyPath">
/// Absolute or relative path to the location of the referenced
/// assembly.
/// </param>
public void AddReference(
string assemblyPath)
{
references.Add(assemblyPath);
}

/// <summary>
/// Allows methods and types from an external library to be referenced
/// within an expression by providing a reference to the already
/// loaded assembly from the calling code.
/// </summary>
/// <param name="assembly">
/// Assembly reference object from the calling scope.
/// </param>
public void AddReference(
Assembly assembly)
{
references.Add(assembly.Location);
}

/// <summary>
/// Allows namespaces to be added to expression execution context so
/// code within expression does not have to fully qualify classes.
/// </summary>
/// <param name="usingNamespace">
/// Fully qualified namespace to be added to the expression execution
/// context, e.g. "System.Collections.Generic".
/// </param>
public void AddUsing(
string usingNamespace)
{
usings.Add(usingNamespace);
}

/// <summary>
/// Allows a method definition to be added to the expression execution
/// context and referenced within the expression.
/// </summary>
/// <param name="methodDefinition">
/// Full definition of the method to add to the expression execution
/// context. Can be public or private, static or non-static.
/// </param>
public void AddMethod(
string methodDefinition)
{
Expand Down Expand Up @@ -275,6 +352,12 @@ private object EvalInternal(string caller)
return result;
}

/// <summary>
/// Executes the expression and returns the resulting value.
/// </summary>
/// <returns>
/// Value specified to be returned from the expression.
/// </returns>
public object Eval()
{
if (!callerInitialized)
Expand All @@ -286,6 +369,16 @@ public object Eval()
return EvalInternal();
}

/// <summary>
/// Executes the expression and returns the resulting value, cast as
/// the specified object type.
/// </summary>
/// <typeparam name="T">
/// Object type to cast the return value as.
/// </typeparam>
/// <returns>
/// Value specified to be returned from the expression.
/// </returns>
public T Eval<T>()
{
if (!callerInitialized)
Expand All @@ -302,20 +395,49 @@ public T Eval<T>()
return cast(answer);
}

/// <summary>
/// Simplified static method to execute an expression and return the
/// resulting value.
/// </summary>
/// <param name="expression">
/// C# based string expression to be evaluated, e.g. "return 1+1".
/// </param>
/// <returns>
/// Value specified to be returned from the expression.
/// </returns>
public static object Eval(string expression)
{
string callerLocation = Assembly.GetCallingAssembly().Location;

return new Evaluator(expression).EvalInternal(callerLocation);
}

/// <summary>
/// Simplified static method to execute an expression and return the
/// resulting value, cast as the specified object type.
/// </summary>
/// <typeparam name="T">
/// Object type to cast the return value as.
/// </typeparam>
/// <param name="expression">
/// C# based string expression to be evaluated, e.g. "return 1+1".
/// </param>
/// <returns>
/// Value specified to be returned from the expression.
/// </returns>
public static T Eval<T>(string expression)
{
string callerLocation = Assembly.GetCallingAssembly().Location;

return (T) new Evaluator(expression).EvalInternal(callerLocation);
}

/// <summary>
/// Executes the expression without returning a value. Resulting
/// new variable values that were updated inside the expression
/// can be subsequently accessed using <see cref="GetVariable(string)"/>
/// or <see cref="this[string]"/>.
/// </summary>
public void Exec()
{
if (!callerInitialized)
Expand Down

0 comments on commit 0d917bc

Please sign in to comment.