我有一个Asp.NET MVC5应用程序,我用这种方式在Startup类中使用Autofac注册我的类型:
public class Startup
{
public void Configuration(IAppBuilder app)
{
IContainer container = null;
var builder = new ContainerBuilder();
// Register Services
builder.RegisterType<SalesRepository>().As<ISalesRepository>().InstancePerRequest();
builder.RegisterType<SalesService>().As<ISalesService>().InstancePerRequest();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.AsClosedTypesOf(typeof(IHandle<>))
.AsImplementedInterfaces()
.InstancePerRequest();
builder.Register<IAppEvents>(_ => new AppEvents(container)).InstancePerRequest();
// Register MVC Controllers
builder.RegisterControllers(Assembly.GetExecutingAssembly());
container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
}
}
这些是我的服务(这是一个简化的场景,仅用于演示)。 SalesService类接收ISalesRepository接口作为依赖项。另外我有一个AppEvents类,我想解决IHandle类型:
public interface ISalesRepository { }
public class SalesRepository : ISalesRepository
{
public SalesRepository() { }
}
public interface ISalesService { }
public class SalesService : ISalesService
{
ISalesRepository _repo;
public SalesService(ISalesRepository repo)
{
_repo = repo;
}
}
public interface IHandle<T>
{
void Handle();
}
public class SalesActionHandle : IHandle<string>
{
ISalesRepository _repo;
public SalesActionHandle(ISalesRepository repo)
{
_repo = repo;
}
public void Handle() { }
}
public interface IAppEvents
{
void Raise<T>();
}
public class AppEvents : IAppEvents
{
private readonly IContainer _container;
public AppEvents(IContainer container)
{
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public void Raise<T>()
{
var handlers = _container.Resolve<IEnumerable<IHandle<T>>>(); // Runtime error here
foreach (var handler in handlers)
handler.Handle();
}
}
这是我唯一的(简化)控制器:
public class HomeController : Controller
{
ISalesService _service;
IAppEvents _events;
public HomeController(ISalesService service, IAppEvents events)
{
_service = service;
_events= events;
}
public ActionResult Index()
{
_events.Raise<string>();
return View();
}
}
我遇到的问题是,执行该行时会出现错误:
var handlers = _container.Resolve<IEnumerable<IHandle<T>>>();
没有标记匹配的范围&#39; AutofacWebRequest&#39;从请求实例的范围中可见。这通常表示SingleInstance()组件(或类似场景)正在请求注册为每HTTP请求的组件。在Web集成下,始终从DependencyResolver.Current或ILifetimeScopeProvider.RequestLifetime请求依赖项,从不从容器本身请求
我通过这样做来解决它:
public void Raise<T>()
{
using (var scope = _container.BeginLifetimeScope("AutofacWebRequest"))
{
var handlers = scope.Resolve<IEnumerable<IHandle<T>>>();
foreach (var handler in handlers)
handler.Handle();
}
}
但在这种情况下,当解决IHandle(使用SalesActionHandle
实例)时,SalesRepository
的新实例将作为SalesActionHandle
构造函数中的参数传递。我想要的是&#34;重用&#34; SalesService
正在使用的相同实例(它是在解析ISalesService
时创建的。我希望请求具有相同的SalesRepository
实例)
有没有办法实现这种行为? 示例代码可在Github中使用:https://github.com/josmonver/AutofacTest
答案 0 :(得分:1)
您可能想要使用
AutofacDependencyResolver.Current.RequestLifetimeScope
匹配您当前的请求范围,但不创建新的请求范围。