【问题标题】:Hook Unity into Web API Filter Attributes将 Unity 挂钩到 Web API 过滤器属性中
【发布时间】:2013-06-26 05:00:55
【问题描述】:

我的 ASP.NET Web API 项目中的所有控制器都运行良好的 Unity - 只需使用来自 NuGet 框的默认设置。我还设法将它连接到 MVC 过滤器属性 - 但似乎不能为 ASP.NET Web API 过滤器属性做同样的事情。

如何扩展此默认实现以将依赖项注入到 ActionFilterAttribute 中,例如...

public class BasicAuthenticationAttribute : ActionFilterAttribute
{
    [Dependency]
    public IMyService myService { get; set; }

    public BasicAuthenticationAttribute()
    {
    }
}

这个过滤器使用属性应用于控制器:

[BasicAuthentication]

我很确定我需要连接 Unity 容器,以便它处理属性类的创建,但需要一些关于从哪里开始的线索,因为它不使用与 MVC 过滤器相同的扩展点。

我只是想补充一下,我尝试过的其他事情包括服务位置而不是依赖注入,但是您返回的 DependencyResolver 与您配置的不一样。

// null
var service = actionContext.Request.GetDependencyScope().GetService(typeof(IMyService));

或者

// null
var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IApiUserService));

【问题讨论】:

    标签: dependency-injection asp.net-web-api unity-container


    【解决方案1】:

    问题在于 Attribute 类是由 .NET 而不是由 WebAPI 框架创建的。

    在继续阅读之前,您是否忘记使用您的 IApiUserService 配置您的 DependencyResolver?

    (IUnityContainer)container;
    container.RegisterType<IApiUserService, MyApiUserServiceImpl>();
    ...
    var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IApiUserService));
    

    我创建了一个 App_Start\UnityConfig 类来保存我的 UnityContainer:

    public class UnityConfig {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });
    
        /// <summary>
        /// Gets the configured Unity container.
        /// </summary>
        public static IUnityContainer GetConfiguredContainer() {
            return container.Value;
        }
        #endregion
    
        public static void Configure(HttpConfiguration config) {
            config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
        }
    
        /// <summary>Registers the type mappings with the Unity container.</summary>
        /// <param name="container">The unity container to configure.</param>
        /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
        /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
        private static void RegisterTypes(IUnityContainer container) {
            // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
            // container.LoadConfiguration();
    
            // TODO: Register your types here
            // container.RegisterType<IProductRepository, ProductRepository>();
            container.RegisterType<MyClass>(new PerRequestLifetimeManager(), new InjectionConstructor("connectionStringName"));
        }
    }
    

    UnityDependencyResolverPerRequestLifetimeManager 来自我内化的 this blog post 和 Unity.WebApi (Project/Nuget Package)。 (因为它是一个引导程序)

    当我需要在其他代码中使用 UnityContainer 时,我将它传递给构造函数:

    config.Filters.Add(new MyFilterAttribute(UnityConfig.GetConfiguredContainer()));
    

    【讨论】:

    • 我从你的回答中剔除了静态方法的想法,它有效。感觉有点不对劲,但鉴于我找不到其他方法,我会接受它:) - 谢谢!
    • 我使用静态工厂的唯一原因是因为我在注册后找不到从 WebAPI 取回 UnityContainer 的方法。但这并没有什么问题。您不想为每个请求或每次请求创建新容器,因此我相信该模式是有效的。
    • 我同意 - 我想重复使用同一个容器,但我希望能够在过滤器属性上方执行这一层。这是我唯一不满意的一点——不是重复使用同一个容器。
    • https://unity.codeplex.com/discussions/446780使用@randylevy点试试
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多