C# 如何在ASP MVC 5中使用MediatR和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

作者介绍了如何使用Autofac在控制台应用程序中使用:

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请求限定范围的EF
DbContext

诀窍是针对当前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);