【发布时间】:2016-01-30 02:00:01
【问题描述】:
我有一个 Asp.NET MVC5 应用程序,我在其中使用 Autofac 以这种方式在 Startup 类中注册我的类型:
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>>>();
从请求实例的范围中看不到带有与“AutofacWebRequest”匹配的标记的范围。这通常表明注册为 per-HTTP 请求的组件正在由 SingleInstance() 组件(或类似场景)请求。在 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 构造函数。我想要的是“重用”SalesService 正在使用的同一个实例(它是在解决 ISalesService 时创建的。我想要相同的 SalesRepository 实例用于请求)
有没有办法实现这种行为? 示例代码在 Github 中可用:https://github.com/josmonver/AutofacTest
【问题讨论】:
标签: c# asp.net-mvc dependency-injection autofac