---
title: "The Context Object"
description: "Event handlers have the sender. But what do custom functions have? Wouldn’t it be nice if there was an analog to the sender parameter, but for every other type of function? Dino defines just such a t…"
url: "https://support.wheelhousemfg.com/article/345mcif8k5-the-context-object"
category: "Dino Script® Language Reference"
updated_at: "2020-01-29T21:09:48Z"
---

# The Context Object

Event handlers have the **sender**. But what do custom functions have? Wouldn’t it be nice if there was an analog to the **sender** parameter, but for every other type of function? Dino defines just such a thing by means of the **context** keyword. Any external function call can set a context callback which will be evaluated by Dino when it encounters the **context** keyword.

```
// let's assume that context is a Sale record with a Customer property.
def cmdCalculateDiscount(discount) {
	var stdDiscount = context.Customer.DiscountLevel;
	var totalDiscount = discount + stdDiscount;

	retun totalDiscount;
}
```

Now, given the code above, imagine that you are editing a **Sale** record. You can see how context is powerful: it allows you to give the user access to custom commands that automatically “pick up” on the context in which they live. In our example, a **Sale** record editing screen. In the **Customer** editing screen, the context would be a **Customer** object. On a list screen, the context might be a list of the currently searched items.

Dino performs this by means of an **IExecuter** object which has a method that looks like this:

```
/// <summary>
/// Calls a function defined in the Dino code, and returns whatever
/// value it returns.
/// </summary>
/// <param name="functionName"></param>
/// <param name="args"></param>
/// <param name="includePrivate"></param>
/// <param name="contextArg"></param>
/// <returns></returns>
public sealed override dynamic CallFunction( string functionName,
	object[] args, bool includePrivate, IContextArgument contextArg = null )
{
	return DinoEvaluator.CallFunction( m_GlobalScope,
		functionName, args, includePrivate, contextArg );
}
```

The executer simply forwards the current global scope to **DinoEvaluator** along with the context callback. The **context** is usually not available and should not be accessed in the global scope. It is intended primarily as an extra argument to a custom function (there is one useful exception to this that is covered below). The best way to think about **context** is as “sender for other functions that are not event handlers”. The following code snippet will make it clearer.

```
def cmdDoThis(aNum, aString) {
	// context might be available
}

var discount = context.Discount; // error, context not available

def onPropertyChanged(sender, e) {
	// sender is available, of course
}

var name = sender.Name; // error, of course sender would not be available here
```

### Expression Evaluation with the Context

There is (of course!) one exception to the “context is only available in a function” rule. One of the stellar uses of Dino is as a powerful expression evaluator, and context can be critical in evaluating one-off expressions, making them far more useful and powerful. The **DinoCompiler** class defines a static method called **Evaluate(…)** which can accept a context object callback which may be accessed in the global scope.

```
/// <summary>
/// Evaluates statements / expressions and returns the result
/// of the last expression.
/// </summary>
/// <param name="script"></param>
/// <param name="getContext">
/// Wrapped in a weak context wrapper.
/// </param>
/// <param name="sandbox"></param>
/// <returns></returns>
public static dynamic Evaluate( ScriptOrString script,
	Func<object> getContext = null, ISandbox sandbox = null )
{
	using( var comp = new DinoCompiler() )
	{
		comp.InitializePrivate( script.GetScript(), sandbox,
			null, null, null, getContext );

		return comp.Result;
	}
}
```

To simplify calling this method, it accepts a **Func&lt;object&gt;** argument for the context instead of the usual **IContextArgument**. Internally, the function wraps the **Func&lt;object&gt;** in a **WeakFuncContextArg** instance (see below). The **Evaluate(…)** function is incredibly useful to simplify unit testing Dino scripts.

But it is for far more than just unit testing. Using the expression evaluator, you can store expressions as properties of a record, then access them to perform dynamic calculations. This is very useful when you need to evaluate expressions for a single, important record, but not for other records of that type. Since the Dino expression lives on the record itself, you can create per-record evaluations.

### The IContextArgument Interface

You may have noticed that the **contextArg** parameter in the **CallFunction** method of **IExecuter** is not a “callback” per se, but is an interface. This enables more flexibility and reuse in accessing the context, because you can create whatever kind of context classes you want, passing necessary objects to the constructor (dependency injection) to help with getting the ultimate object.

The **IContextArgument** interface couldn’t be much simpler. It defines a single method, **GetContext()**, which returns an **object** and takes no arguments.

```
/// <summary>
/// Used to pass a context callback to a script function from outside.
/// </summary>
public interface IContextArgument
{
	/// <summary>
	/// Resolves the context object.
	/// </summary>
	/// <returns></returns>
	object GetContext();
}
```

Dino defines one built-in implementation of this interface in the form of the **WeakFuncContextArg**, the full code of which is shown here for reference.

```
/// <summary>
/// Holds a weak reference to a Func<object>. Do not pass anonymous
/// functions to the constructor of this object, because if so it will be
/// garbage collected almost immediately. Rather, pass in a func that is
/// stored as a local or member variable, or a property. See the examples for
/// guidance on this. Then, when the variable or property is eligible for
/// GC, the delegate passed to this will also be GC'ed.
/// <example>
/// <code>
/// BAD EXAMPLE:
/// var obj = new object();
/// var weakFunc = new WeakFuncContextArg(() => obj); // NO!!
/// GOOD EXAMPLE:
/// var obj = new object();
/// Func<object> func = () => obj; // or maybe a lot more complex...
/// var weakFunc = new WeakFuncContextArg(func);
/// </code>
/// </example>
/// </summary>
public sealed class WeakFuncContextArg : IContextArgument
{
	private WeakReference<Func<object>> m_GetContext;

	/// <summary>
	/// Constructs a weak reference to a Func<object>. See examples
	/// on class comments for correct calling convention.
	/// </summary>
	/// <param name="getContext"></param>
	public WeakFuncContextArg( Func<object> getContext )
	{
		if( null == getContext )
			throw new ArgumentNullException( "getContext" );

		m_GetContext = new WeakReference<Func<object>>( getContext );
	}

	/// <summary>
	/// Dereferences the weak reference and returns the result of
	/// evaluating the func contained in it.
	/// </summary>
	/// <returns></returns>
	public object GetContext()
	{
		Func<object> target;
		m_GetContext.TryGetTarget( out target );
		if( null == target )
			return null;

		return target();
	}
}
```
