【问题标题】:How to reuse an InstancePerRequest instance create in composition root using Autofac如何重用使用 Autofac 在组合根中创建的 InstancePerRequest 实例
【发布时间】: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


    【解决方案1】:

    您可能想使用 AutofacDependencyResolver.Current.RequestLifetimeScope 匹配您当前的请求范围,但不创建新的请求范围。

    【讨论】:

    • 它有效。我可以在 AppEvents 构造函数中注入 ILifetimeScope (AutofacDependencyResolver.Current.RequestLifetimeScope):public AppEvents(ILifetimeScope scope),因此 AppEvents 类不依赖于 Autofac.Integration.Mvc(及其依赖项):builder.Register&lt;IAppEvents&gt;(_ =&gt; new AppEvents(AutofacDependencyResolver.Current.RequestLifetimeScope)).InstancePerRequest();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多