Dependency injection 如何使用ASP.NET MVC 3 RTM配置依赖项注入
我正在将一个web应用程序从ASP.NET 3 Preview 1升级到RTM,我对更新的依赖注入方法感到困惑。我正在使用StructureMap,但这与我的问题无关。之前,我需要做的是: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、
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();
}
}
}