Я пытался следовать этому статья о том, как внедрить свои зависимости в мой собственный LogActionFilter, но я не могу лгать. Я полностью сбит с толку и нуждаюсь в некоторой помощи с достижением финишной черты (я добавляю свои зависимости в мой фильтр настраиваемых действий, а также с объяснением того, как это делается. Пока что у меня есть это:
IActionFilter:
public interface IActionFilter<TAttribute> where TAttribute : Attribute {
void OnActionExecuting(TAttribute attribute, ActionExecutingContext context);
}
LogActionDecorator:
public class LogActionDecorator<TAttribute> : IActionFilter<TAttribute>
where TAttribute : Attribute {
private readonly IActionFilter<TAttribute> _decoratee;
private readonly IAccountManagementManager _iAccountManagementManager;
public LogActionDecorator(
IActionFilter<TAttribute> decoratee,
IAccountManagementManager iAccountManagementManager) {
this._decoratee = decoratee;
this._iAccountManagementManager = iAccountManagementManager;
}
public void OnActionExecuting(TAttribute attribute, ActionExecutingContext context) {
this._decoratee.OnActionExecuting(attribute, context);
}
}
ActionFilterDispatcher:
public class ActionFilterDispatcher : IActionFilter {
private readonly Func<Type, IEnumerable> _container;
public ActionFilterDispatcher(Func<Type, IEnumerable> container) {
this._container = container;
}
public void OnActionExecuted(ActionExecutedContext filterContext) { }
public void OnActionExecuting(ActionExecutingContext context) {
var descriptor = context.ActionDescriptor;
var attributes = descriptor.ControllerDescriptor.GetCustomAttributes(true)
.Concat(descriptor.GetCustomAttributes(true))
.Cast<Attribute>();
foreach (var attribute in attributes) {
Type filterType = typeof(IActionFilter<>)
.MakeGenericType(attribute.GetType());
IEnumerable filters = this._container.Invoke(filterType);
foreach (dynamic actionFilter in filters) {
actionFilter.OnActionExecuting((dynamic)attribute, context);
}
}
}
}
LogActionFiter:
public class LogActionFilter : IActionFilter<ActionFilterAttribute> {
private readonly IAccountManagementManager _iAccountManagementManager;
public LogActionFilter(IAccountManagementManager iAccountManagementManager) {
_iAccountManagementManager = iAccountManagementManager;
}
public void OnActionExecuting(
ActionFilterAttribute attribute, ActionExecutingContext context) {
var fg = _iAccountManagementManager.ReturnApplicationIDAsync();
}
}
Контроллер:
[LogActionFilter] //Build error LogActionFilter is not an attribute class
public class AccountManagementController : Controller {
public async Task<ActionResult> EndImpersonation() {
//Do stuff
}
}
Может ли кто-нибудь помочь мне внедрить мои зависимости в мой фильтр настраиваемых действий, а также объяснить, как это делается? DI иногда действительно трудно понять
Привет, Стивен, я надеялся, что ты ответишь ха-ха. Вы правы, вчера был долгий день, и я не совсем понимал, как эта статья сочетается друг с другом. Я еще раз посмотрел, переработал свой код и заставил его работать. Я считаю, что понимаю, как код сочетается друг с другом, но не «зачем» мне нужно делать это для DI для атрибутов. Я собираюсь перечитать вашу статью, чтобы попытаться лучше понять. Спасибо





Вы должны пометить свой контроллер ActionFilterAttribute вместо LogActionFilter.
Спасибо за ваш комментарий и ответ. Они оба помогли, я добавил ответ своим кодом, но вы сказали мне, как туда добраться, поэтому я выбрал это в качестве ответа
IActionFilter:
/// <summary>
/// My ActionFilter which takes an Attribute
/// </summary>
/// <typeparam name = "TAttribute">The attribute type(E.g ActionFilterAttribute)</typeparam>
public interface IActionFilter<TAttribute> where TAttribute : Attribute {
//My OnActionExecuting method which will be called when an Action is being executed. It can be extended to include other methods such as OnActionExecuted if required
void OnActionExecuting(TAttribute attribute, ActionExecutingContext context);
}
ActionFilterDispatcher:
/// <summary>
/// The dispatcher(which gets added to the GlobalFilters) requires the simple injector container which contains all instances of injected classes.
/// Inherit from the MVC library IActionFilter in order to gain access to the OnActionExecuting method
/// </summary>
public class ActionFilterDispatcher : IActionFilter {
private readonly Func<Type, IEnumerable> _container;
public ActionFilterDispatcher(Func<Type, IEnumerable> container) {
this._container = container;
}
public void OnActionExecuted(ActionExecutedContext filterContext) { }
public void OnActionExecuting(ActionExecutingContext context) {
var descriptor = context.ActionDescriptor;
//Get all attributes on a controller/action and cast them to the generic Attribute class
var attributes = descriptor.ControllerDescriptor.GetCustomAttributes(true)
.Concat(descriptor.GetCustomAttributes(true))
.Cast<Attribute>();
//Foreach attribute call the OnActionExecuting method for the IActionFilter of the attribute(E.g LogActionDecoraor)
foreach (var attribute in attributes) {
Type filterType = typeof(IActionFilter<>).MakeGenericType(attribute.GetType());
IEnumerable filters = this._container.Invoke(filterType);
foreach (dynamic actionFilter in filters) {
actionFilter.OnActionExecuting((dynamic)attribute, context);
}
}
}
}
LogActionDecorator:
/// <summary>
/// This is where the decoratee(E.g. the LogActionFilter) gets called. It is also where the implementation is contained
/// </summary>
/// <typeparam name = "TAttribute"></typeparam>
public class LogActionDecorator<TAttribute> : IActionFilter<TAttribute> where TAttribute : Attribute {
private readonly IActionFilter<TAttribute> _decoratee;
public LogActionDecorator(IActionFilter<TAttribute> decoratee, IAccountManagementManager iAccountManagementManager) {
this._decoratee = decoratee;
}
public void OnActionExecuting(TAttribute attribute, ActionExecutingContext context) {
this._decoratee.OnActionExecuting(attribute, context);
}
}
LogActionFilter:
/// <summary>
/// My custom ActionFilter for the LogActionAttribute. This is the class which gets called to complete the implementation of the attribute
/// </summary>
public class LogActionFilter : IActionFilter<LogActionAttribute> {
private readonly IAccountManagementManager _iAccountManagementManager;
public LogActionFilter(IAccountManagementManager iAccountManagementManager) {
_iAccountManagementManager = iAccountManagementManager;
}
public void OnActionExecuting(LogActionAttribute attribute, ActionExecutingContext context) {
var fg = _iAccountManagementManager.ReturnApplicationIDAsync();
}
}
LogActionAttribte:
/// <summary>
/// This is my custom ActionFilterAttribute. It is passive(contains no code) as the implementation will be taken care of in my LogActionFilter
/// </summary>
public class LogActionAttribute : ActionFilterAttribute {
}
Контроллер:
[LogActionAttribute]
public class AccountManagementController : Controller {
public async Task<ActionResult> EndImpersonation() {
//Do stuff
}
}
Стивен был прав, я не понял сути статьи. Во всяком случае, вот мой обновленный код.
Я думаю, что ошибка, которую вы делаете, вызвана непониманием того, чего пытается достичь статья. Идея состоит в том, чтобы иметь пассивные (без кода) атрибуты, подкрепленные полностью функциональными компонентами. Контроллер должен зависеть от атрибута, а не от компонента.