Mithilfe von Unity injizieren von Abhängigkeiten in einem benutzerdefinierten ActionFilter
Im moment habe ich eine eigene ControllerFactory, in die ich Spritzen mein Unity-container:
in global.asax Application_Start():
var container = InitContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
var factory = new UnityControllerFactory(container);
ControllerBuilder.Current.SetControllerFactory(factory);
In der controller factory habe ich meine Controller für die Verwendung einer benutzerdefinierten ActionInvoker etwa so:
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;
}
Endlich in meine eigene ActionInvoker, ich Versuch zum Aufbau Aktionen aufgerufen wird, mit dem ActionInvokers container:
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);
}
Hier ist ein Beispiel für eine der ActionFilters wird aufgebaut:
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();
}
}
}
Das problem ist, dass die öffentliche Eigenschaft auf meine benutzerdefinierte ActionFilterAttribute wird nie eingespritzt wird, nichts, es bleibt null bei der Ausführung! Ich kann nicht sehen, warum mein filter nicht mehr richtig builtup durch den container. Die Art injiziert werden, ordnungsgemäß registriert ist, wie so:
container.RegisterInstance(new ChannelFactory<IMetadataService>(
new BasicHttpBinding(),
new EndpointAddress("http://example.com/ABSApplication/MetadataService.svc")));
container.RegisterInstance<Func<IMetadataService>>(
() => container.Resolve<ChannelFactory<IMetadataService>>().CreateChannel());
Ist und auch injiziert, die an anderer Stelle in der Anwendung (wenn auch nicht über .Anhaftungen). Das ist so ziemlich der gleiche Prozess, gefolgt von dieser blog-post. Welche Puzzleteile fehlen mir?
- Aus Neugier, warum nicht dies tun, sagen, Authentifizierung verlangen, preauth Anfrage, etc und cache Sie (session, etc), so dass Sie es für jede Anforderung, während der Benutzer angemeldet ist?
- Meine ursprüngliche Absicht war es, die Kapselung dieser Funktionalität, so dass ich hinzufügen könnte, wenn eine Aktion gefordert wurde. Wenn nach der überprüfung war ich die Daten von der Filter eine erhebliche Menge, ich würde sicherlich cache Global für die Wiederverwendung in der gesamten Anwendung. Es ist eigentlich Anfang zu schauen, wie das wäre eine einfachere Lösung sowieso, unabhängig davon verwerten! Ich bin immer noch sehr neugierig, warum
container.BuildUp
funktioniert nicht aber. - Ich fand dieses Beispiel, gehen check it out kurz. Der Quellcode steht zum download gibt, als auch msdn.microsoft.com/en-us/gg618494
- Ich hatte gesehen, dass Artikel, die mich dazu veranlasste, weiter zu Fragen link hier. Auf der Suche über den code in diesem Artikel, es scheint etwas unvollständig. Ich sehe nicht, wo die benutzerdefinierte IFilterProvider angeschlossen ist. Sicherlich nur registrieren es in Ihrem container ist nicht genug für Sie eingesetzt werden. Es nicht vermeiden, die Frage oben gepostet mit Aufbau.
- Wenn ich nicht bekommen, eine Antwort bald in Bezug auf, warum Aufbau nicht funktionieren würde, im ursprünglichen Szenario, ich akzeptiere Ihre Antwort, wie ich bin dankbar für die Bestätigung, dass ich denken, entlang den gleichen Linien wie andere devs würden: -)
- auch würde ich überlegen, dies zu tun, wie ein auth-filter, um sicherzustellen, dass diese zuerst ausgeführt wird, bevölkern Sie alles oder die Rollen, die möglicherweise nicht verfügbar für zukünftige Steuerungen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde dies etwas anders. Ich würde:
installieren Sie die Einheit.mvc3-nuget-Paket
Aufruf der Bootstrap.initialisieren() wie bereits in der txt-doc-Paket fügt dem Projekt
definieren Sie Ihre IMetadataService Zuordnung in der Initialisierung auf Ihre Konkreten Typ
hinzufügen IMetadataService zu Ihrem Konstruktor
Die Differenz zwischen der Umsetzung und der Artikel, den Sie Verweise, die Sie verwenden, Func, die Im nicht sicher, ob das fügt ein anderes problem in den mix hier. Ich habe das so vorstellen, als nicht mit der oben beschriebenen Methode (ohne Funk) funktioniert gut für mich.
Bearbeiten:
Brad Wilson ' s code hat Prima funktioniert für mich hier:
http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html
Geltende Teile (siehe link oben)
Global.asax.cs
Den filter selbst:
und UnityFilterAttributeFilterProvider.cs
[PopulatRoles] public ActionResult Add() {
wie kann ich erreichen, Injektion bei der PopulateRoles ActionFilterAttribute? Ich kann constructor injection wie es ein Attribut, und ich nicht nutzen kann man den Konstruktor verwendet. Deshalb brauche ich zum Aufbau des Attributs, wie es erstellt wird.public PopulateOfficesAttribute(Func<IMetadataService> service)
zu erreichen constructor injection ist, dann würde ich angeben müssen, dass arg, wenn Sie das Attribut im code '[PopulateOffices(Arg)]', sonst wird es nicht kompiliert. Wenn ich versuche, verwenden Sie property-injection, MVC framework nicht auflösen, die Abhängigkeit innerhalb der ActionFilterAttribute für mich - nur getestet um sicher zu gehen 🙂 Wenn Sie finden, dass es nicht anders sein, lass es mich wissen!Unity Bootstrapper for ASP.NET MVC
Paket hat alle diese Arbeit für Sie.