代码之家  ›  专栏  ›  技术社区  ›  n8wrl

autofac、asp.net和microsoft.practices.servicelocation

  •  1
  • n8wrl  · 技术社区  · 15 年前

    我一直在研究在我的Web应用程序中实现IOC的细节,但以一种利用microsoft.practices.servicelocation的方式。我专门使用autopac和ASP.NET集成,但我想让自己打开其他容器。沿着 this question ,我担心如何访问我的Web应用程序代码中的容器。

    我有一个“核心”库,它主要定义要解析的接口。这个核心库也被我的Web应用程序和其他应用程序使用。定义公共接口非常方便。我认为这是一个很好的地方,可以访问IOC容器,我用了一个静态类来实现这一点。技巧是将容器注入静态类。

    在Web环境中,这是很棘手的,因为容器对于每个请求可能是不同的,而在非Web应用程序中,容器可能总是相同的。起初,我尝试用一个方法注入容器direclty,但在下一个Web请求中很快失败了!所以我想到了这个:

    public static class IoCContainer
    {
        public static void SetServiceLocator(Func<IServiceLocator> getLocator)
        {
            m_GetLocator = getLocator;
        }
        static private Func<IServiceLocator> m_GetLocator = null;
    
        public static T GetInstance<T>(string typeName)
        {
            return m_GetLocator().GetInstance<T>(typeName);
        }
    }
    

    现在在我的global.asax.cs中,我这样做:

    protected void Application_Start(object sender, EventArgs e)
    {
        var builder = new Autofac.Builder.ContainerBuilder();
        ... register stuff ...
        var container = builder.Build();
        _containerProvider = new Autofac.Integration.Web.ContainerProvider(container);
        Xyz.Core.IoCContainer.SetServiceLocator(() => 
            new AutofacContrib.CommonServiceLocator.AutofacServiceLocator
                (_containerProvider.RequestContainer));
    }
    public IContainerProvider ContainerProvider
    {
        get { return _containerProvider; }
    }
    static IContainerProvider _containerProvider;
    

    解决依赖关系的呼吁

    var someService = Xyz.Core.GetInstance<ISomeService>();
    

    因此,我不传递特定的容器,而是传递一个知道如何获取容器的委托。对于非Web应用程序,委托可能只返回builder.build()提供的服务。

    我要问的是,这有道理吗?我有一个简单的方法可以解决依赖关系,而不知道容器产品是什么或者容器本身来自哪里。你怎么认为?

    1 回复  |  直到 15 年前
        1
  •  2
  •   Peter Lillevold Rene    15 年前

    我们使用类似的模式,主要是因为IOC被引入到非DI架构中。因此需要能够显式地调用容器来获取服务,这基本上是工厂模式。

    当所有依赖项都可以注入并且您的代码不再依赖于服务定位器时,IOC的真正好处就实现了。autopac.integration.web有一些处理程序可以对页面对象执行注入,这将使静态服务定位器过时。IMO这是首选的方式,尽管(在我们的案例中)服务定位器不能总是被避免。

    这就是说,由于您已经使用ioccontainer类将应用程序与容器隔离开来,所以我认为没有理由在ioccontainer中额外抽象autopacservicelocator。归根结底,ioccontainer已经是您的服务定位器,应该“允许”直接访问容器实现。

    这是我对您的服务定位器类的看法:

    public static class IoCContainer
    {
        private static IContext GetContainer()
        {
            var cpa = 
                 (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
            return cpa.ContainerProvider.RequestContainer;
        }
    
        public static T GetInstance<T>()
        {
            return GetContainer().Resolve<T>();
        }
    }