【问题标题】:How to inject constructor/properties properly in ASP.NET HttpModule with Simple Injector如何使用 Simple Injector 在 ASP.NET HttpModule 中正确注入构造函数/属性
【发布时间】:2014-11-16 15:54:33
【问题描述】:

我有一个名为UsersOnlineModule 的类是从IHttpModul 创建的。在这个类中,我想注入两个属性,为此我使用Simple Injector。

public class UsersOnlineModule
{
    public ITenantStore tenantStore;
    public ICacheManager cm;

我从 IHttpModule 调用这个类:

Modules.UsersOnline.UsersOnlineModule usersOnlineModule =
    new Modules.UsersOnline.UsersOnlineModule();
usersOnlineModule.TrackUser(app.Context);

但是我的IHttpModule 不知道缓存管理器或tenantStore。我可以通过从容器中获取对象来解决这个问题,但是我不希望创建对 Simple Injector 的引用。有没有其他不错的选择来解决这两个属性而不创建对我的容器的引用?

-- 更新

我将示例修改如下:

class ImportAttributePropertySelectionBehavior : IPropertySelectionBehavior
{
    public bool SelectProperty(Type serviceType, PropertyInfo propertyInfo)
    {
        return typeof(IHttpModule).IsAssignableFrom(serviceType) &&
            propertyInfo.GetCustomAttributes<ImportAttribute>().Any();
    }
}

private static void RegisterHttpModules(Container container)
{
    var httpModules =
        from assembly in BuildManager.GetReferencedAssemblies().Cast<Assembly>()
        where !assembly.IsDynamic
        where !assembly.GlobalAssemblyCache
        from type in assembly.GetExportedTypes()
        where type.IsSubclassOf(typeof(IHttpModule))
        select type;

    httpModules.ToList().ForEach(container.Register);
}

但它没有返回我的任何 httpmodules。

【问题讨论】:

    标签: c# asp.net dependency-injection simple-injector


    【解决方案1】:

    integration guide 展示了如何使用 HttpModule 来初始化 HttpHandlers。但是,不会为每个请求创建一个 HttpModule;它为应用程序创建一次,并在调用其初始化方法时注册到HttpApplication 的事件。

    因为一个模块是一个单例,你不应该将依赖注入到你的模块中。您应该解决每个请求的依赖关系,并且由于 HttpModule 无法配置并且不是它自己的依赖关系,因此您必须从 HttpModule 中回调容器。确实没有其他办法,但这里的诀窍是尽量减少所需的代码量。示例:

    public class UsersOnlineModule : IHttpModule
    {
        public void Init(HttpApplication context) {
            context.PreRequestHandlerExecute += (s, e) => {
                var handler = Global.GetInstance<UsersOnlineHandler>();
                handler.Handle();
            };
        }
    }
    

    在此示例中,UsersOnlineModule 所做的只是解析一个服务并在其上调用其方法。此服务(在本例中为UsersOnlineHandler)应捕获所需的所有逻辑和依赖项。所以换句话说,你的HttpModule变成了Humble Object,所有的逻辑都被提取到UsersOnlineHandler中:

    public class UsersOnlineHandler
    {
        private readonly ITenantStore tenantStore;
        private readonly ICacheManager cm;
    
        public UsersOnlineHandler(ITenantStore tenantStore, ICacheManager cm) {
            this.tenantStore = tenantStore;
            this.cm = cm;
        }
    
        public void Handle() {
           // logic here
        }
    }
    

    警告: 请确保不要将任何依赖项存储到 HttpModule 的类或实例字段或属性中,因为这可能会导致依赖项变为 Captive Dependency。相反,如上所述,只需在该方法调用中解决、使用和忘记该依赖关系。不要存放它。

    【讨论】:

    • 嗨史蒂文,我看过这个,但我不明白它是如何使我的 IHttpModules 松散耦合的,因为现在模块需要了解我的 MvcApplication 对象才能动态注册自己?
    • 诀窍是您制作一个与 DI 容器紧密耦合的 HttpModule,它是组合根的一部分。通过这个单一的 HttpModule,您可以添加许多其他完全不依赖于容器的 HttpModule。他们只是使用一个属性(自定义或由 .NET 框架)来标记要注入的属性。
    • 啊,更有意义。我刚刚修改了示例以查看 IHttpModules 而不是 Page,因为我正在使用 MVC,但是我没有让它工作..我明天再试一些。
    • 好的,我现在迷路了,我已经修改了所有内容,但是我现在在 init 方法中的 MvcHandler 上遇到异常,并且我的 HttpModule 属性没有被注入.....叹息,我我猜我最终会在我的模块中使用容器......
    • @user3188048:对不起,我误导了你。请查看我的更新。
    猜你喜欢
    • 2013-01-11
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多