Added non-generic registration interface to IKernel and IWindsor to accommodate dynam...
[castle.git] / MonoRail / Castle.MonoRail.Framework / Services / DefaultControllerTree.cs
blob2759d7d9bec8f15f87e000aecfb9332c33a9144c
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Framework.Services
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
21 /// <summary>
22 /// Default implementation of <see cref="IControllerTree"/>.
23 /// Represents an binary tree of registered controllers.
24 /// <para>
25 /// It is used by the controller factory to resolve a controller instance
26 /// based on the specified area (which is optional) and controller name
27 /// </para>
28 /// <seealso cref="IControllerTree"/>
29 /// <seealso cref="Castle.MonoRail.Framework.Services.AbstractControllerFactory"/>
30 /// </summary>
31 public sealed class DefaultControllerTree : IControllerTree
33 /// <summary>
34 /// The area the controller belongs to.
35 /// The default area is <c>String.Empty</c>
36 /// </summary>
37 private readonly String area;
39 /// <summary>
40 /// A dictionary of controllers that belongs to this node (area)
41 /// </summary>
42 private readonly IDictionary controllers;
44 /// <summary>
45 /// The controllers node on the left
46 /// </summary>
47 private DefaultControllerTree left;
49 /// <summary>
50 /// The controllers node on the right
51 /// </summary>
52 private DefaultControllerTree right;
54 /// <summary>
55 /// Occurs when a controller is added to the controller tree.
56 /// </summary>
57 public event EventHandler<ControllerAddedEventArgs> ControllerAdded;
59 /// <summary>
60 /// Constructs a <c>ControllerTree</c> with an empty area
61 /// </summary>
62 public DefaultControllerTree() : this(String.Empty)
66 /// <summary>
67 /// Constructs a <c>ControllerTree</c> specifying an area
68 /// </summary>
69 public DefaultControllerTree(String areaName)
71 if (areaName == null) throw new ArgumentNullException("areaName");
73 area = areaName;
74 controllers = new HybridDictionary(true);
77 private void OnControllerAdded(String area, String controllerName, Type controller)
79 if (ControllerAdded != null)
81 ControllerAddedEventArgs args = new ControllerAddedEventArgs(area, controllerName, controller);
82 ControllerAdded(this, args);
86 /// <summary>
87 /// Register a controller on the tree. If the specified
88 /// area name matches the current node, the controller is
89 /// register on the node itself, otherwise on the right or
90 /// on the left node.
91 /// </summary>
92 /// <remarks>
93 /// Note that the controller is an <c>object</c>. That allows
94 /// different implementation of a controller factory to register
95 /// different representation of what a controller is (a name, a descriptor etc)
96 /// </remarks>
97 /// <param name="areaName">The area name, or <c>String.Empty</c></param>
98 /// <param name="controllerName">The controller name</param>
99 /// <param name="controller">The controller representation</param>
100 public void AddController(String areaName, String controllerName, Type controller)
102 if (areaName == null) throw new ArgumentNullException("areaName");
103 if (controllerName == null) throw new ArgumentNullException("controllerName");
104 if (controller == null) throw new ArgumentNullException("controller");
106 int cmp = String.Compare(areaName, area, true);
108 if (cmp == 0)
110 // If it's the same area, register the controller
111 controllers[controllerName] = controller;
113 else
115 // Otherwise, check if the controller should be registered
116 // on the left or on the right
118 DefaultControllerTree node;
120 if (cmp < 0)
122 if (left == null)
124 left = new DefaultControllerTree(areaName);
126 node = left;
128 else
130 if (right == null)
132 right = new DefaultControllerTree(areaName);
134 node = right;
137 node.AddController(areaName, controllerName, controller);
138 OnControllerAdded(areaName, controllerName, controller);
142 /// <summary>
143 /// Returns a controller previously registered.
144 /// </summary>
145 /// <param name="areaName">The area name, or <c>String.Empty</c></param>
146 /// <param name="controllerName">The controller name</param>
147 /// <returns>The controller representation or null</returns>
148 public Type GetController(String areaName, String controllerName)
150 if (areaName == null) throw new ArgumentNullException("areaName");
151 if (controllerName == null) throw new ArgumentNullException("controllerName");
153 int cmp = String.Compare(areaName, area, true);
155 if (cmp == 0)
157 return (Type) controllers[controllerName];
159 else
161 DefaultControllerTree node;
163 if (cmp < 0)
165 node = left;
167 else
169 node = right;
172 if (node != null)
174 return node.GetController(areaName, controllerName);
178 return null;
182 /// <summary>
183 /// Event class that represents details of the controller added
184 /// to the controller tree
185 /// </summary>
186 public sealed class ControllerAddedEventArgs : System.EventArgs
188 private readonly String area;
189 private readonly String controllerName;
190 private readonly Type controllerType;
192 /// <summary>
193 /// Initializes a new instance of the <see cref="ControllerAddedEventArgs"/> class.
194 /// </summary>
195 /// <param name="area">The area.</param>
196 /// <param name="controllerName">Name of the controller.</param>
197 /// <param name="controllerType">Type of the controller.</param>
198 public ControllerAddedEventArgs(string area, string controllerName, Type controllerType)
200 this.area = area;
201 this.controllerName = controllerName;
202 this.controllerType = controllerType;
205 /// <summary>
206 /// Gets the area.
207 /// </summary>
208 /// <value>The area.</value>
209 public string Area
211 get { return area; }
214 /// <summary>
215 /// Gets the name of the controller.
216 /// </summary>
217 /// <value>The name of the controller.</value>
218 public string ControllerName
220 get { return controllerName; }
223 /// <summary>
224 /// Gets the type of the controller.
225 /// </summary>
226 /// <value>The type of the controller.</value>
227 public Type ControllerType
229 get { return controllerType; }