简单的注入器MVC ActionFilter依赖注入

时间:2018-05-08 23:30:55

标签: c# asp.net-mvc dependency-injection

我一直在努力完成关于如何将我的依赖项注入自定义LogActionFilter的{​​{3}},但我不能说谎。我很困惑,需要一些帮助才能到达终点线(I.E将我的依赖项注入我的自定义动作过滤器,并解释它是如何完成的。到目前为止我有这个:

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有时候很难理解

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

IActionFilter:

class TFloatNum {
  public:
    float N;
};

void __fastcall TForm1::btnAddClick(TObject *Sender)
{
  TFloatNum G;
  G.N = 75.5;
  StringList1->AddObject("a", G);
}

ActionFilterDispatcher:

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

LogActionDecorator:

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

LogActionFilter:

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

LogActionAttribte:

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

位指示:

/// <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 {
}
史蒂文是对的,我不明白这篇文章的重点。无论如何,这是我更新的代码。