gpt4 book ai didi

c# - 我可以让 WebApi 与 IoC Aspects/Interceptor 一起工作吗

转载 作者:太空宇宙 更新时间:2023-11-03 23:48:03 25 4
gpt4 key购买 nike

我有 WCF 背景,我成功地将 IoC 与方面/拦截器结合使用来抽象功能,例如身份验证和日志记录。我会简单地将所需的接口(interface)添加到方面构造函数,就像您使用任何典型的 IoC 设置一样。

我现在正尝试将相同类型的过程应用于 webapi,但由于 Controller 继承自 ApiController 并且不实现接口(interface)。我假设可能有不同的应用方面的方式?

public class MyController: ApiController
{
private readonly IUnitOfWork _unitOfWork;
private readonly ILoginService _loginService;
private readonly ILog _log;

public LoginController(ILoginService loginService, IUnitOfWork unitOfWork, ILog log)
{
this._loginService = loginService;
this._unitOfWork = unitOfWork;
this._log = log;
}

// I WANT TO INTERCEPT THIS METHOD USING UserTokenAuthenticationInterceptor
public HttpResponseMessage Get(Guid id)
{
_log.Log(log something);
// some code thats gets some data using this._loginService
_log.Log(log the save);
_unitOfWork.Save();
}
}

看点

public class UserTokenAuthenticationInterceptor : IInterceptionBehavior 
{
private readonly ILoginService _loginService;
private readonly ILog _log;

public UserTokenAuthenticationInterceptor(ILog log, ILoginService loginService)
{
this._log = log;
this._loginService = loginService;
}

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
_log.Log(log entering authentication aspect);
// do some authentication here using this._loginService
_log.Log(log exiting authentication aspect);
}

public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}

public bool WillExecute { get { return true; }}
}

容器注册:

container.RegisterType<IUnitOfWork, UnitOfWork.UnitOfWork>(new HierarchicalLifetimeManager());
container.RegisterType<ILoginService , LoginService>();
container.RegisterType<ILog, LogService>();

我在这个例子中使用了 unity。谁能指出我正确的方向?

最佳答案

感谢大家的帮助,我终于弄明白了。

我从这篇文章中得到了大部分答案 https://unity.codeplex.com/discussions/446780

我使用了以下 nuget 包。

  • Unity(我先加了这1个)
  • Unity.WebApi(如果不先添加unity会有unity版本问题)

首先,我需要一个新的 IFilterProvider 实现。它的工作是向容器注册所有 Action 过滤器。

public class UnityActionFilterProvider : ActionDescriptorFilterProvider, IFilterProvider
{
private readonly IUnityContainer container;

public UnityActionFilterProvider(IUnityContainer container)
{
this.container = container;
}

public new IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(configuration, actionDescriptor);

foreach (var filter in filters)
{
container.BuildUp(filter.Instance.GetType(), filter.Instance);
}

return filters;
}
}

然后需要一个注册方法,注册新的actionfilterprovider,去掉原来的webapi实现。这需要在 Unity.WebApi nuget 包创建的 UnityConfig.cs 文件中的 RegisterComponents() 方法中执行。

public static void RegisterFilterProviders(IUnityContainer container)
{
var providers = GlobalConfiguration.Configuration.Services.GetFilterProviders().ToList();

GlobalConfiguration.Configuration.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider),
new UnityActionFilterProvider(container));

var defaultprovider = providers.First(p => p is ActionDescriptorFilterProvider);

GlobalConfiguration.Configuration.Services.Remove(typeof(System.Web.Http.Filters.IFilterProvider), defaultprovider);

}

在同一个 RegisterComponents() 方法中我注册了我的类型

container.RegisterType<IUnitOfWork, UnitOfWork.UnitOfWork>(new HierarchicalLifetimeManager());
container.RegisterType<ILoginService , LoginService>();
container.RegisterType<ILog, LogService>();

接下来,我需要创建一个基于 AuthorizeAttribute 的类。

public class UserTokenAuthenticationAttribute : AuthorizeAttribute
{
private ILoginService _loginService;

// This is the magic part - Unity reads this attribute and sets injects the related property. This means no parameters are required in the constructor.
[Microsoft.Practices.Unity.Dependency]
public ILoginService LoginService
{
get
{
return this._loginService;
}
set
{
this._loginService = value;
}
}

protected override bool IsAuthorized(HttpActionContext actionContext)
{
// Authorise code goes here using injected this._loginService
}
}

还需要一个日志 Action 过滤器ActionFilterAttribute

public sealed class LogAttribute : ActionFilterAttribute
{
private ILog _log;

// This is the magic part - Unity reads this attribute and sets injects the related property. This means no parameters are required in the constructor.
[Microsoft.Practices.Unity.Dependency]
public ILog Log
{
get
{
return this._log;
}
set
{
this._log = value;
}
}

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
this._log.Info("Exited " + actionContext.Request.Method);
}

public override void OnActionExecuting(HttpActionContext actionContext)
{
this._log.Info("Entering" + actionContext.Request.Method);
}
}

现在让我们配置 webapi Controller 。我们需要用我们的新属性来装饰这个类

[UserTokenAuthentication] // magic attribute in use
[Log] // magic attribute in use
public class MyController: ApiController
{
private readonly IUnitOfWork _unitOfWork;
private readonly ILoginService _loginService;
private readonly ILog _log;

public MyController(ILoginService loginService, IUnitOfWork unitOfWork, ILog log)
{
this._loginService = loginService;
this._unitOfWork = unitOfWork;
this._log = log;
}

[System.Web.Http.AllowAnonymous] // doesnt require authentication as were not logged in yet
public HttpResponseMessage Get(Guid id)
{
_log.Log(log something);
// some code thats gets some data using this._loginService
_log.Log(log the save);
_unitOfWork.Save();
}

public HttpResponseMessage GetMyDetails(Guid id)
{
_log.Log(log something);
// some code thats gets some data using this._loginService
_log.Log(log the save);
_unitOfWork.Save();
}
}

关于c# - 我可以让 WebApi 与 IoC Aspects/Interceptor 一起工作吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26907512/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com