C# 如何在WebApi中为属性实现DI?

C# 如何在WebApi中为属性实现DI?,c#,dependency-injection,attributes,ninject,asp.net-web-api,C#,Dependency Injection,Attributes,Ninject,Asp.net Web Api,我重构了一个在Web api中实现基本Http身份验证的属性,使其具有DI,如下所示: public class BasicHttpAuthAttribute : ActionFilterAttribute { private readonly ILoginManager _manager; public BasicHttpAuthAttribute(ILoginManager manager) { this._

我重构了一个在Web api中实现基本Http身份验证的属性,使其具有DI,如下所示:

 public class BasicHttpAuthAttribute : ActionFilterAttribute
    {
        private readonly ILoginManager _manager;

        public BasicHttpAuthAttribute(ILoginManager manager)
        {
            this._manager = manager;
        }
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (actionContext.Request.Headers.Authorization == null)
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                actionContext.Response.Content = new StringContent("Missing Auth-Token");
            }
            else
            {

                var authToken = actionContext.Request.Headers.Authorization.Parameter;
                var decodedToken = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));

                string userName = decodedToken.Substring(0, decodedToken.IndexOf(":"));
                string password = decodedToken.Substring(decodedToken.IndexOf(":") + 1);


                UserInfo user;


                if (_manager.LoginPasswordMatch(userName, password, out user))
                {
                    var apiUser = new ApiUser(user.UserID);
                    HttpContext.Current.User = new GenericPrincipal(new ApiIdentity(apiUser), new string[]{});

                    base.OnActionExecuting(actionContext);

                }
                else
                {
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                    actionContext.Response.Content = new StringContent("Invalid username or password");
                }



            }
        }
    }
在重构之前,我在OnActionExecuting中创建了LoginManager的一个实例(它本身没有DI,所以我可以使用一个构造函数创建一个实例)。重构后的问题是,构建失败,因为当我将过滤器应用于WebApi方法时,它期望在那里有一个参数


在这种情况下,当LoginManager本身在其构造函数中使用ILoginRepository时,如何实现DI?甚至可能吗?

最简单的方法是使构造函数不需要参数,而是使用不同的注入形式。具体的实现方式取决于您使用的DI容器。例如,使用Unity,您可以创建一个默认构造函数。创建另一个公共方法(我通常将其称为Initialize以清除),并用[InjectionMethod]属性修饰它。然后,在构造函数内部,只需调用container.build(this);这基本上允许MVC调用它想要的默认构造函数,但是您的InjectionMethod总是作为构建过程的一部分自动调用


对于其他DI容器,也有类似的方法来做同样的事情,但是在不知道您在使用什么的情况下,单元示例是最容易解释的。

最容易的选择是使它成为构造函数不需要参数,而是使用不同的注入形式。具体的实现方式取决于您使用的DI容器。例如,使用Unity,您可以创建一个默认构造函数。创建另一个公共方法(我通常将其称为Initialize以清除),并用[InjectionMethod]属性修饰它。然后,在构造函数内部,只需调用container.build(this);这基本上允许MVC调用它想要的默认构造函数,但是您的InjectionMethod总是作为构建过程的一部分自动调用


对于其他DI容器,也有类似的方法来做同样的事情,但是在不知道您在使用什么的情况下,单元示例是最容易解释的。

这并不容易,因为在Web API中处理属性的方式与您可能期望的有点不同。首先,它们是在不同的时间点创建的,其次是缓存的

话虽如此,实现DI的最简单方法不是通过构造函数注入,而是在处理时调用您选择的DI框架,然后检索依赖项,即在
onActionExecuting
中:

var s = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IService));

这并不容易,因为在WebAPI中处理属性的方式与您可能期望的有点不同。首先,它们是在不同的时间点创建的,其次是缓存的

话虽如此,实现DI的最简单方法不是通过构造函数注入,而是在处理时调用您选择的DI框架,然后检索依赖项,即在
onActionExecuting
中:

var s = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IService));

您无法控制
BasicHttpAuthAttribute
的实例化,因此无法使用正确的DI

您可以在属性的构造函数中使用
ServiceLocator
来提供所需的依赖项,也可以使用一些容器为现有对象提供的
build
功能

Unity这样做是为了支持非自己创建的第三方对象的
building

对于您的属性,这意味着创建类型为
ILoginManager
的公共可写属性,并告诉容器将您的管理器注入该属性


您不必使用
DependencyAttribute
btw来污染您的属性。向容器注册您的属性类型,并提供
InjectionProperty(“NameOfPropertyToInject”)
作为该注册的参数。

您无法控制
BasicHttpAuthAttribute
的实例化,因此无法使用正确的DI

您可以在属性的构造函数中使用
ServiceLocator
来提供所需的依赖项,也可以使用一些容器为现有对象提供的
build
功能

Unity这样做是为了支持非自己创建的第三方对象的
building

对于您的属性,这意味着创建类型为
ILoginManager
的公共可写属性,并告诉容器将您的管理器注入该属性

您不必使用
DependencyAttribute
btw来污染属性。向容器注册属性类型,并提供
InjectionProperty(“NameOfPropertyToInject”)
作为该注册的参数