Al momento, ho un ControllerFactory personalizzato in cui mi inietto il mio contenitore Unità:con Unity per iniettare le dipendenze in un personalizzato ActionFilter
a global.asax Application_Start():
var container = InitContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
var factory = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(factory);
Nel controller fabbrica ho impostato il mio controller per utilizzare un ActionInvoker personalizzato in questo modo:
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
var controller = base.GetControllerInstance(requestContext, controllerType) as Controller;
if (controller != null)
controller.ActionInvoker = new UnityActionInvoker(_container);
return controller;
}
Infine nel mio ActionInvoker personalizzato, tento di azioni accumulo essere invocati usando il contenitore ActionInvokers:
protected override ActionExecutedContext InvokeActionMethodWithFilters(
ControllerContext controllerContext,
IList<IActionFilter> filters,
ActionDescriptor actionDescriptor,
IDictionary<string, object> parameters)
{
var builtUpFilters = new List<IActionFilter>();
foreach (IActionFilter actionFilter in filters)
{
builtUpFilters.Add(_container.BuildUp<IActionFilter>(actionFilter));
}
return base.InvokeActionMethodWithFilters(controllerContext, builtUpFilters, actionDescriptor, parameters);
}
Ecco un esempio di una delle ActionFilters che si sta costruendo in su:
public class PopulatRolesAttribute : ActionFilterAttribute, IActionFilter
{
private const string RolesKey = "roles";
[Dependency]
public Func<IMetadataService> Service { get; set; }
public PopulatRolesAttribute()
{
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.Controller.ViewData[RolesKey] == null)
{
filterContext.Controller.ViewData[RolesKey] = Service().GetRoles();
}
}
}
Il problema è che la proprietà pubblica sulla mia abitudine ActionFilterAttribute non è mai iniettato con qualsiasi cosa, rimane nullo in esecuzione! Non riesco a capire perché il mio filtro non sia stato correttamente creato dal contenitore. Il tipo di essere iniettato è registrato correttamente, in questo modo:
container.RegisterInstance(new ChannelFactory<IMetadataService>(
new BasicHttpBinding(),
new EndpointAddress("http://example.com/ABSApplication/MetadataService.svc")));
container.RegisterInstance<Func<IMetadataService>>(
() => container.Resolve<ChannelFactory<IMetadataService>>().CreateChannel());
E viene anche iniettato in altre parti dell'applicazione (Anche se non tramite .Buildup). Questo è praticamente lo stesso processo seguito da questo blog post. Quale parte del puzzle mi manca?
Per curiosità, perché non farlo in diciamo, autenticare richiesta, richiesta preauth, ecc e li memorizza nella cache (sessione, ecc) in modo che non ci sono per ogni richiesta mentre l'utente è connesso? –
La mia intenzione originale era di incapsulare questa funzionalità in modo che potessi aggiungerla ogni volta che un'azione lo richiedeva. Se dopo la revisione stavo per utilizzare i dati recuperati dai filtri di una quantità significativa, sicuramente lo memorizzerei in una cache globale per riutilizzarli in tutta l'applicazione. In realtà sta iniziando a sembrare che sarebbe comunque una soluzione più semplice, indipendentemente dal riutilizzo! Sono ancora molto curioso del perché 'container.BuildUp' non funzioni comunque. –
Ho trovato questo esempio, andando a controllare a breve. La fonte è disponibile per il download anche qui http://msdn.microsoft.com/en-us/gg618494 –