C# 如何在ASP MVC 5中使用MediatR和Autofac?
作者介绍了如何使用Autofac在控制台应用程序中使用:C# 如何在ASP MVC 5中使用MediatR和Autofac?,c#,asp.net-mvc,dependency-injection,autofac,mediatr,C#,Asp.net Mvc,Dependency Injection,Autofac,Mediatr,作者介绍了如何使用Autofac在控制台应用程序中使用: var builder = new ContainerBuilder(); builder.RegisterSource(new ContravariantRegistrationSource()); builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces(); builder.RegisterAssemblyTypes(type
var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof (Ping).Assembly).AsImplementedInterfaces();
builder.RegisterInstance(Console.Out).As<TextWriter>();
var lazy = new Lazy<IServiceLocator>(() => new AutofacServiceLocator(builder.Build()));
var serviceLocatorProvider = new ServiceLocatorProvider(() => lazy.Value);
builder.RegisterInstance(serviceLocatorProvider);
var builder=newcontainerbuilder();
RegisterSource(新的ContrariantRegistrationSource());
RegisterAssemblyTypes(typeof(IMediator.Assembly).assemplementedInterfaces();
RegisterAssemblyTypes(typeof(Ping.Assembly).AsImplementedInterfaces();
builder.RegisterInstance(Console.Out).As();
var lazy=new lazy(()=>new AutofacServiceLocator(builder.Build());
var serviceLocatorProvider=newservicelocatorprovider(()=>lazy.Value);
builder.RegisterInstance(serviceLocatorProvider);
我举了这个例子,并试图让它与ASP MVC 5和软件包一起工作:
var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(AddPostCommand).Assembly).AsImplementedInterfaces();
builder.RegisterControllers(typeof(HomeController).Assembly);
var container = builder.Build();
var lazy = new Lazy<IServiceLocator>(() => new AutofacServiceLocator(container));
var serviceLocatorProvider = new ServiceLocatorProvider(() => lazy.Value);
builder.RegisterInstance(serviceLocatorProvider);
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
var builder=newcontainerbuilder();
RegisterSource(新的ContrariantRegistrationSource());
RegisterAssemblyTypes(typeof(IMediator.Assembly).assemplementedInterfaces();
RegisterAssemblyTypes(typeof(AddPostCommand.Assembly).AsImplementedInterfaces();
构建器.注册表控制器(typeof(HomeController).Assembly);
var container=builder.Build();
var lazy=new lazy(()=>new AutofacServiceLocator(容器));
var serviceLocatorProvider=newservicelocatorprovider(()=>lazy.Value);
builder.RegisterInstance(serviceLocatorProvider);
SetResolver(新的AutofacDependencyResolver(容器));
当我运行web应用程序时,会收到一个错误页面,告诉我,ServiceLocationProvider
依赖项尚未注册。我做错了什么
我怀疑这个问题是由于我在调用
Build
之后注册了ServiceLocatorProvider
实例造成的-在作者的示例中,由于Lazy
,之后调用了Build
方法。不过,我不知道如何解决这个问题 无法在完成类型注册之前调用Builder.Build
在您的示例中,在调用Builder.RegisterInstance之前调用Builder.Build,这解释了为什么它无法在运行时推断类型
我在今天遇到同样的问题后提出了这个问题,但它正在进行中,因为它还没有解决我的实现问题
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof(HomePageThumbnail).Assembly).AsImplementedInterfaces();
var lifetimeScope = new Lazy<ILifetimeScope>(() => builder.Build());
var lazy = new Lazy<IServiceLocator>(() => new AutofacServiceLocator(lifetimeScope.Value));
var serviceLocatorProvider = new ServiceLocatorProvider(() => lazy.Value);
builder.RegisterInstance(serviceLocatorProvider);
DependencyResolver.SetResolver(new AutofacDependencyResolver(lifetimeScope.Value));
app.UseAutofacMiddleware(lifetimeScope.Value);
app.UseAutofacMvc();
这引发了一个例外
An exception of type 'Microsoft.Practices.ServiceLocation.ActivationException' occurred in Microsoft.Practices.ServiceLocation.dll but was not handled in user code
Additional information: Activation error occurred while trying to get instance of type IRequestHandler`2, key ""
这与MediatR中包含的Autofac示例项目中提供的基于约定的注册相同,我也尝试过显式注册它
builder.RegisterType<RecentActivityThumbnailsHandler>().As<IRequestHandler<RecentActivityThumbnailsQuery, RecentActivityThumbnailsResults>>();
builder.RegisterType().As();
我会在它工作时更新。如果您在我之前就解决了,请执行同样的操作。我在正确注册
中介
和ServiceLocatorProvider
类时遇到问题。我拉扯了一下头发,但最终还是摆脱了它 我的错误是针对根Autofac容器注册了
ServiceLocatorProvider
,如下所示:
var-lazyContainer=newlazy(()=>builder.Build());
Register(x=>newservicelocatorprovider(()=>newautofacserviceloator(lazyContainer.Value));
SetCurrent(新的AutofacDependencyResolver(lazyContainer.Value));
在运行时,Autofac抛出异常,因为我的一个请求
依赖于我配置为由HTTP请求限定范围的EFDbContext
诀窍是针对当前HTTP请求注册ServiceLocatorProvider
谢天谢地,来自Autofac的错误消息是不言自明的:
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance
was requested. This generally indicates that a component registered as per-HTTP request is being
requested by a SingleInstance() component (or a similar scenario.) Under the web integration
always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime,
never from the container itself.
发生这种情况的原因是AutofacServiceLocator
由根容器提供。当请求解析
DbContext
时,容器不知道与当前HTTP请求作用域关联的内部上下文
使用JustDecompile,我发现实现ILifetimeScopeProvider
接口的唯一类是AutofacDependencyResolver
,您可以使用静态属性AutofacDependencyResolver.current
访问当前实例
如错误消息中所述,您可以使用AutofacDependencyResolver.current.RequestLifetimeScope访问当前的ILifetimeScope
,因此最终注册如下:
builder
.Register(x=>new ServiceLocator提供程序(()=>new AutofacServiceLocator(AutofacDependencyResolver.Current.RequestLifetimeScope)))
.InstancePerHttpRequest();
InstancePerHttpRequest()
部分是可选的,但由于在整个HTTP请求期间,ILifetimeScope
将是相同的,这会阻止Autofac创建n个AutofacServiceLocator
的实例
希望这是清楚的,如果您觉得有必要,请不要犹豫进行一些编辑,因为我很难清楚地解释这一点。我正在使用Webapi 2+Autofac+OWIN并设法使其工作。以下是我的代码: 这是我的autofac构造函数
//Constructor
var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();
// Register Web API controller in executing assembly.
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
var lazyContainer = new Lazy<IContainer>(() => builder.Build());
var serviceLocatorProvider = new ServiceLocatorProvider(() => new AutofacServiceLocator(lazyContainer.Value));
builder.RegisterInstance(serviceLocatorProvider);
config.DependencyResolver = new AutofacWebApiDependencyResolver(lazyContainer.Value);
// This should be the first middleware added to the IAppBuilder.
app.UseAutofacMiddleware(lazyContainer.Value);
// Make sure the Autofac lifetime scope is passed to Web API.
app.UseAutofacWebApi(config);
一切都很好,不必解释注册每个requestHandler或CommandHandler。因为我也浪费了很多时间来整理它,我真的希望它能帮助其他有同样问题的人。过去的答案有助于解决这个问题
更新:
好的,我只是重构de代码,以删除所有的惰性绑定,使其更简单。下面是更改:
而不是:
var lazyContainer = new Lazy<IContainer>(() => builder.Build());
var serviceLocatorProvider = new ServiceLocatorProvider(() => new AutofacServiceLocator(lazyContainer.Value));
builder.RegisterInstance(serviceLocatorProvider);
var-lazyContainer=newlazy(()=>builder.Build());
var serviceLocatorProvider=newservicelocatorprovider(()=>newautofacservicelocator(lazyContainer.Value));
builder.RegisterInstance(serviceLocatorProvider);
只需使用:
builder.RegisterType<AutofacServiceLocator>().AsImplementedInterfaces();
var container = builder.Build();
//ServiceLocator.SetLocatorProvider(serviceLocatorProvider);
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
builder.RegisterType();
var container=builder.Build();
//ServiceLocator.SetLocatorProvider(serviceLocatorProvider);
config.DependencyResolver=新的AutoFacWebApidencyResolver(容器);
var lazyContainer = new Lazy<IContainer>(() => builder.Build());
var serviceLocatorProvider = new ServiceLocatorProvider(() => new AutofacServiceLocator(lazyContainer.Value));
builder.RegisterInstance(serviceLocatorProvider);
builder.RegisterType<AutofacServiceLocator>().AsImplementedInterfaces();
var container = builder.Build();
//ServiceLocator.SetLocatorProvider(serviceLocatorProvider);
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);