简体   繁体   English

简单注入器MVC ActionFilter依赖注入

[英]Simple injector MVC ActionFilter dependency injection

I have been trying to follow through this article on how to inject my dependencies into my custom LogActionFilter but I can't lie. 我一直在尝试阅读这篇文章 ,了解如何将依赖项注入到自定义LogActionFilter但我不能撒谎。 I'm thoroughly confused and require some help with reaching the finishing line(IE injecting my dependencies into my custom action filter and also with the explanation of how it is done. So far I have this: 我很困惑,需要一些帮助才能达到终点(即将依赖项注入到我的自定义操作过滤器中,以及如何完成操作的解释。到目前为止,我已经做到了:

IActionFilter: IActionFilter:

public interface IActionFilter<TAttribute> where TAttribute : Attribute {
    void OnActionExecuting(TAttribute attribute, ActionExecutingContext context);
}

LogActionDecorator: 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: 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: 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();
    }
}

Controller: 控制器:

[LogActionFilter] //Build error LogActionFilter is not an attribute class
public class AccountManagementController : Controller {

    public async Task<ActionResult> EndImpersonation() {
      //Do stuff
    }
}

Can someone help me with injecting my dependencies into my custom action filter and also explain how this is done? 有人可以帮助我将依赖项注入到自定义操作过滤器中,还可以解释如何完成此操作吗? DI is sometimes really hard to understand DI有时真的很难理解

您必须使用ActionFilterAttribute而不是LogActionFilter标记控制器。

IActionFilter: 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: 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: 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: 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: 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 {
}

Contoller: 位指示:

[LogActionAttribute] 
public class AccountManagementController : Controller {

    public async Task<ActionResult> EndImpersonation() {
      //Do stuff
    }
}

Steven was right, I didn't understand the point of the article. 史蒂文是对的,我不明白本文的重点。 Anyway, here is my updated code. 无论如何,这是我更新的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM