Files
Umbraco-CMS/src/Umbraco.Web/Mvc/MasterControllerFactory.cs
2013-02-20 06:30:06 +06:00

107 lines
4.5 KiB
C#

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using System.Web.Routing;
using Umbraco.Core;
namespace Umbraco.Web.Mvc
{
/// <summary>
/// A controller factory which uses an internal list of <see cref="IFilteredControllerFactory"/> in order to invoke
/// different controller factories dependent upon their implementation of <see cref="IFilteredControllerFactory.CanHandle"/> for the current
/// request. Allows circumvention of MVC3's singly registered IControllerFactory.
/// </summary>
/// <remarks></remarks>
internal class MasterControllerFactory : DefaultControllerFactory
{
private readonly FilteredControllerFactoriesResolver _slaveFactories;
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
private readonly ConcurrentDictionary<string, Type> _controllerCache = new ConcurrentDictionary<string, Type>();
public MasterControllerFactory(FilteredControllerFactoriesResolver factoryResolver)
{
_slaveFactories = factoryResolver;
}
/// <summary>
/// Creates the specified controller by using the specified request context.
/// </summary>
/// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
/// <param name="controllerName">The name of the controller.</param>
/// <returns>The controller.</returns>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext"/> parameter is null.</exception>
///
/// <exception cref="T:System.ArgumentException">The <paramref name="controllerName"/> parameter is null or empty.</exception>
/// <remarks></remarks>
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var factory = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
return factory != null
? factory.CreateController(requestContext, controllerName)
: base.CreateController(requestContext, controllerName);
}
/// <summary>
/// Retrieves the controller type for the specified name and request context.
/// </summary>
///
/// <returns>
/// The controller type.
/// </returns>
/// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
/// <param name="controllerName">The name of the controller.</param>
internal Type GetControllerTypeInternal(RequestContext requestContext, string controllerName)
{
var factory = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
if (factory != null)
{
//check to see if the factory is of type UmbracoControllerFactory which exposes the GetControllerType method so we don't have to create
// an instance of the controller to figure out what it is. This is a work around for not having a breaking change for:
// http://issues.umbraco.org/issue/U4-1726
var umbFactory = factory as UmbracoControllerFactory;
if (umbFactory != null)
{
return umbFactory.GetControllerType(requestContext, controllerName);
}
//we have no choice but to instantiate the controller
var instance = factory.CreateController(requestContext, controllerName);
if (instance != null)
{
return instance.GetType();
}
return null;
}
return base.GetControllerType(requestContext, controllerName);
}
/// <summary>
/// Releases the specified controller.
/// </summary>
/// <param name="controller">The controller to release.</param>
/// <remarks></remarks>
public override void ReleaseController(IController controller)
{
using (new WriteLock(_locker))
{
bool released = false;
if (controller is Controller)
{
var requestContext = ((Controller)controller).ControllerContext.RequestContext;
var factory = _slaveFactories.Factories.FirstOrDefault(x => x.CanHandle(requestContext));
if (factory != null)
{
factory.ReleaseController(controller);
released = true;
}
}
if (!released) base.ReleaseController(controller);
}
}
}
}