谢谢大家的帮助,我终于弄明白了。
我从这篇文章中得到了大部分答案https://unity.codeplex.com/discussions/446780
我使用了以下 nuget 包。
- Unity(我先加了这个1)
- Unity.WebApi(如果没有先添加统一,则存在统一版本问题)
首先,我需要一个新的 IFilterProvider 实现。它的工作是将所有动作过滤器注册到容器中。
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
}
}
还需要一个日志操作过滤器 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 控制器。我们需要用我们的新属性来装饰这个类
[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();
}
}