简体   繁体   中英

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. 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:

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

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

您必须使用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 {
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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