Usage Scenarios
The usage scenarios will assume the TypeInstanceDictionary is being used in an ASP.NET MVC application to pass data from the controller to the view.
Using the TypeInstanceDictionary in a ASP.NET MVC controller
To make access to the TypeInstanceDictionary convenient in a controller derive all controllers from a base controller that provides a property exposing the dictionary via a property.
public class BaseController : Controller
{
ITypeInstanceDictionary _typedViewData = new TypeInstanceDictionary();
public ITypeInstanceDictionary TypedViewData
{
get
{
return _typedViewData;
}
set
{
_typedViewData = value;
}
}
}In a controller derived from BaseContoller can then use the dictionary as follows:
public ActionResult Index()
{
HomeViewData viewData = new HomeViewData();
viewData.Message = "Welcome to ASP.NET MVC!";
viewData.Message2 = "And welcome again!";
viewData.Message3 = "And welcome yet again!";
TypedViewData.Add<HomeViewData>(viewData);
return View(TypedViewData);
}
Using the view data in an ASP.NET MVC View
To consume the TypeViewDictionary in a view specify ITypeViewDictionary in all view definitions for the type of the model:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TTC.Tools.ITypeInstanceDictionary>" %>
The view code can then used the data in the view model as follows:
<h2><%= Model.Get<HomeViewData>().Message %></h2>
<p>
To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
</p>
<p>
<%= Model.Get<HomeViewData>().Message2 %>
</p>
<p>
<%= Model.Get<HomeViewData>().Message3 %>
</p>
The TypeInstanceDictionary has a Verify function which can be used to check for the existence of a certain type. The intended use in an ASP.NET MVC view is to place Verify calls at the top of the page markup as a check to make sure required view model data has been added by the controller. Verify calls can be chained to check for n types.
If a view requires the dictionary to hold an IFu and IFu2 interface in the dictionary then you can check as follows:
<% Model.Verify<IFu>().Verify<IFu2>(); %>
If the dictionary does not contain a type of IFu or IFu2 an exception will be thrown by the Verify function.
Adding and retrieving entries using the TypeInstanceDictionary¶
Assuming you have the classes Fu which implements interface IFu you can add values to the dictionary as follows:
ITypeInstanceDictionary dict = new TypeInstanceDictionary();
IFu fu = new Fu();
dict.Add(fu);
dict.Get<IFu>();
Fu fu2 = new Fu();
dict.Add(fu2);
dict.Get<Fu>();
The dictionary Add
will default to using the type of the argument, so specifying the type on the Add call is optional. The previous code is equivalent to:
ITypeInstanceDictionary dict = new TypeInstanceDictionary();
IFu fu = new Fu();
dict.Add<IFu>(fu);
dict.Get<IFu>();
Fu fu2 = new Fu();
dict.Add<Fu>(fu2);
dict.Get<Fu>();
The type must always be specified for the Get as the dictionary entry is indexed by type.
Adding multiple instances of the same type
To add multiple instances of the same type, a unique identifier must be supplied to the Add call. The instance identifier can be an integer, string, or the type can be specified in the template version of Add where I is the type of instance identifier.
ITypeInstanceDictionary dict = new TypeInstanceDictionary();
IFu fu = new Fu();
dict.Add(fu, "Fu1");
IFu fu2 = new Fu();
dict.Add(fu2, "Fu2");
dict.Get<IFu>("Fu1");
dict.Get<IFu>("Fu2");
Using a string or integer is a bit obscure. In fact, TypeInstanceDictionary exists because the default ViewData mechanism in ASP.NET MVC uses a string key to access dictionary members. I'm not a fan of string indexers :-) A coder always tends to have to search all over to determine what string value to use.
One choice is to use an enumeration and cast the enumerated value to an int on the Add call:
enum InstanceType { Instance1, Instance2 }
ITypeInstanceDictionary dict = new TypeInstanceDictionary();
IFu fu = new Fu();
dict.Add(fu, (int)InstanceType.Instance1);
IFu fu2 = new Fu();
dict.Add(fu2, (int)InstanceType.Instance2);
dict.Get<IFu>((int)InstanceType.Instance1);
dict.Get<IFu>((int)InstanceType.Instance2);
The casting seems a bit cumbersome and has the problem that multiple enumerations with the same underlying integer value will collide. TypeInstanceDictionary is coded to use the string representation of the type plus the enumeration value as the instance id for enumerated type. So, the enumerated type can be used in a similar manner when casting the enumeration to an int with the exception that the enumerated type needs to be specified as the type of the instance id for the Get call.
ITypeInstanceDictionary dict = new TypeInstanceDictionary();
IFu fu = new Fu();
dict.Add(fu, InstanceType.Instance1);
IFu fu2 = new Fu();
dict.Add(fu2, InstanceType.Instance2);
dict.Get<IFu, InstanceType>(InstanceType.Instance1);
dict.Get<IFu, InstanceType>(InstanceType.Instance2);
How to check if an instance of a type exists
Check to find out if a type exists in the dictionary using the Contains function. The contains function has the same overloads as Add and Get to allow checking using the various instance id flavors.
For example:
ITypeInstanceDictionary dict = new TypeInstanceDictionary();
IFu fu = new Fu();
dict.Add(fu);
bool dictContainsIFu = dict.Contains<IFu>(); // Returns true.
bool dictContainsIFu2 = dict.Contains<IFu2>(); // Returns false. No IFu2 instance has been added.