Dependency injection 如何使用ASP.NET MVC 3 RTM配置依赖项注入

Dependency injection 如何使用ASP.NET MVC 3 RTM配置依赖项注入,dependency-injection,asp.net-mvc-3,structuremap,Dependency Injection,Asp.net Mvc 3,Structuremap,我正在将一个web应用程序从ASP.NET 3 Preview 1升级到RTM,我对更新的依赖注入方法感到困惑。我正在使用StructureMap,但这与我的问题无关。之前,我需要做的是: x.For<IControllerFactory>().Use<DefaultControllerFactory>(); x.For<IServiceLocator>().Use(MvcServiceLocator.Current); x.For().Use(); x、

我正在将一个web应用程序从ASP.NET 3 Preview 1升级到RTM,我对更新的依赖注入方法感到困惑。我正在使用StructureMap,但这与我的问题无关。之前,我需要做的是:

x.For<IControllerFactory>().Use<DefaultControllerFactory>();
x.For<IServiceLocator>().Use(MvcServiceLocator.Current);
x.For().Use();
x、 For().Use(MvcServiceLocator.Current);
现在看来我需要提供IControllerActivator、IViewPageActivator和ModelMetadataProvider的实现,因为否则我会从StructureMap中得到一个错误,因为MVC试图使用依赖项解析器来定位它们。从MVC源代码来看,似乎没有公开的默认实现。我在设置这些时是否遗漏了什么?当然这些应该按照约定进行配置

请举例说明需要配置什么以及如何使用StructureMap。作为参考,我目前正在使用以下难看的乱码,这迫使MVC使用其内部默认值:

x.For<IControllerFactory>().Use<DefaultControllerFactory>();
x.For<IDependencyResolver>().Use(() => DependencyResolver.Current);                
x.For<IControllerActivator>().Use(() => null);
x.For<IViewPageActivator>().Use(() => null);
x.For<ModelMetadataProvider>().Use(ModelMetadataProviders.Current);
x.For().Use();
x、 For()。使用(()=>DependencyResolver.Current);
x、 For()。使用(()=>null);
x、 For()。使用(()=>null);
x、 For().Use(ModelMetadataProviders.Current);

编辑:我有一个依赖项解析程序的工作StructureMap实现-问题是为什么MVC抱怨容器中没有配置所有这些接口。

我能够通过创建依赖项解析程序(IDependencyResolver)类使StructureMap与ASP.NET MVC3一起工作,然后在global.asax中注册该类。我还没有完全测试这段代码。但是,它在两个应用程序中都没有出现任何问题

StructureMappDependencyResolver.cs

using System.Linq;
using System.Web.Mvc;
using StructureMap;

namespace SomeNameSpace
{
    public class StructureMapDependencyResolver : IDependencyResolver
    {
        private readonly IContainer container;

        public StructureMapDependencyResolver(IContainer container)
        {
            this.container = container;
        }

        public object GetService(System.Type serviceType)
        {
            try
            {
                return this.container.GetInstance(serviceType);
            }
            catch
            {
                return null;
            }
        }

        public System.Collections.Generic.IEnumerable<object> GetServices(System.Type serviceType)
        {
            return this.container.GetAllInstances<object>()
                .Where(s => s.GetType() == serviceType);
        }
    }
}

多亏了迈克尔·卡曼(Michael Carman)在其回答的评论中发布的链接,我才明白这一点。我不确定这里的礼节是否值得接受他的实际答案,因为这不太正确(我给了他+1票),但我想我应该发布自己的答案,解释到底是什么问题

问题在于我的IDependencyResolver实现和容器配置的组合。最初我有:

public class StructureMapDependencyResolver : IDependencyResolver
{
    public object GetService(Type serviceType)
    {
        return ObjectFactory.GetInstance(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        foreach (object obj in ObjectFactory.GetAllInstances(serviceType))
        {
            yield return obj;
        }
    }
}
公共类结构MapDependencyResolver:IDependencyResolver
{
公共对象GetService(类型serviceType)
{
返回ObjectFactory.GetInstance(serviceType);
}
公共IEnumerable GetServices(类型serviceType)
{
foreach(ObjectFactory.GetAllInstances(serviceType)中的对象obj)
{
收益率目标;
}
}
}
但我现在根据中的链接更改为:

公共类结构MapDependencyResolver:IDependencyResolver
{
公共对象GetService(类型serviceType)
{
if(serviceType.IsAbstract | | serviceType.IsInterface)
{
返回ObjectFactory.TryGetInstance(serviceType);
}
其他的
{
返回ObjectFactory.GetInstance(serviceType);
}
}
公共IEnumerable GetServices(类型serviceType)
{
foreach(ObjectFactory.GetAllInstances(serviceType)中的对象obj)
{
收益率目标;
}
}
}
在我删除此配置表达式之前,这本身仍然无法解决问题:

x.For<IControllerFactory>().Use<DefaultControllerFactory>();
x.For().Use();

根据文档,TryGetInstance只返回容器中注册的类型,如果不存在,则返回null。我假设MVC 3代码依赖于这种行为来指示它应该使用其默认值,因此在我最初的例子中,我必须将这些默认值注册到我的容器中。狡猾的一个

这对我来说适用于MVC和Web API

namespace Web.Utilities.DependencyResolvers
{
    public class StructureMapResolver : IServiceLocator, IDependencyResolver
    {
        private readonly IContainer _container;

        public StructureMapResolver(IContainer container)
        {
            if (container == null)
                throw new ArgumentNullException("container");

            this._container = container;
        }

        public IDependencyScope BeginScope()
        {
            return new StructureMapResolver(this._container.GetNestedContainer());
        }

        public object GetInstance(Type serviceType, string instanceKey)
        {
            if (string.IsNullOrEmpty(instanceKey))
            {
                return GetInstance(serviceType);
            }

            return this._container.GetInstance(serviceType, instanceKey);
        }

        public T GetInstance<T>()
        {
            return this._container.GetInstance<T>();
        }

        public object GetService(Type serviceType)
        {
            return GetInstance(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return this._container.GetAllInstances(serviceType).Cast<object>();
        }

        public T GetInstance<T>(string instanceKey)
        {
            return this._container.GetInstance<T>(instanceKey);
        }

        public object GetInstance(Type serviceType)
        {
            return serviceType.IsAbstract || serviceType.IsInterface ?
                this._container.TryGetInstance(serviceType) : this._container.GetInstance(serviceType);
        }

        public IEnumerable<T> GetAllInstances<T>()
        {
            return this._container.GetAllInstances<T>();
        }

        public IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return this._container.GetAllInstances(serviceType).Cast<object>();
        }

        public void Dispose()
        {
            this._container.Dispose();
        }
    }
}
namespace Web.Utilities.DependencyResolver
{
公共类结构映射解析器:IServiceLocator,IDependencyResolver
{
专用只读IContainer\u容器;
公共结构映射解析器(IContainer容器)
{
if(容器==null)
抛出新的ArgumentNullException(“容器”);
这个._容器=容器;
}
公共IDependencyScope BeginScope()
{
返回新的StructureMapResolver(this.\u container.GetNestedContainer());
}
公共对象GetInstance(类型serviceType,字符串instanceKey)
{
if(string.IsNullOrEmpty(instanceKey))
{
返回GetInstance(serviceType);
}
返回此._container.GetInstance(serviceType,instanceKey);
}
公共T GetInstance()
{
返回此。_container.GetInstance();
}
公共对象GetService(类型serviceType)
{
返回GetInstance(serviceType);
}
公共IEnumerable GetServices(类型serviceType)
{
返回此。_container.GetAllInstances(serviceType).Cast();
}
public T GetInstance(字符串instanceKey)
{
返回此._container.GetInstance(instanceKey);
}
公共对象GetInstance(类型serviceType)
{
返回serviceType.IsAbstract | | serviceType.IsInterface?
this.\u container.TryGetInstance(serviceType):this.\u container.GetInstance(serviceType);
}
公共IEnumerable GetAllInstances()
{
返回此文件。_container.GetAllInstances();
}
公共IEnumerable GetAllInstances(类型serviceType)
{
返回此。_container.GetAllInstances(serviceType).Cast();
}
公共空间处置()
{
此._container.Dispose();
}
}
}

这也是我设置它的方式,它对我很有效。但我不确定这与以前的版本有什么不同,我们使用了DefaultControllerFactory的一个子类,它是在调用ControllerBuilder的当前属性时设置的。您使用RTM版本吗?您的注册中心是否有任何相关的设置代码?
x.For<IControllerFactory>().Use<DefaultControllerFactory>();
namespace Web.Utilities.DependencyResolvers
{
    public class StructureMapResolver : IServiceLocator, IDependencyResolver
    {
        private readonly IContainer _container;

        public StructureMapResolver(IContainer container)
        {
            if (container == null)
                throw new ArgumentNullException("container");

            this._container = container;
        }

        public IDependencyScope BeginScope()
        {
            return new StructureMapResolver(this._container.GetNestedContainer());
        }

        public object GetInstance(Type serviceType, string instanceKey)
        {
            if (string.IsNullOrEmpty(instanceKey))
            {
                return GetInstance(serviceType);
            }

            return this._container.GetInstance(serviceType, instanceKey);
        }

        public T GetInstance<T>()
        {
            return this._container.GetInstance<T>();
        }

        public object GetService(Type serviceType)
        {
            return GetInstance(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return this._container.GetAllInstances(serviceType).Cast<object>();
        }

        public T GetInstance<T>(string instanceKey)
        {
            return this._container.GetInstance<T>(instanceKey);
        }

        public object GetInstance(Type serviceType)
        {
            return serviceType.IsAbstract || serviceType.IsInterface ?
                this._container.TryGetInstance(serviceType) : this._container.GetInstance(serviceType);
        }

        public IEnumerable<T> GetAllInstances<T>()
        {
            return this._container.GetAllInstances<T>();
        }

        public IEnumerable<object> GetAllInstances(Type serviceType)
        {
            return this._container.GetAllInstances(serviceType).Cast<object>();
        }

        public void Dispose()
        {
            this._container.Dispose();
        }
    }
}