简体   繁体   English

具有Autofac的ASP.Net MVC构造函数注入-运行时参数

[英]ASP.Net MVC Constructor Injection with Autofac - Runtime parameters

I am reasonably new to Autofac and have come up against a problem when injecting dependencies that have arguments that are only known at runtime. 我对Autofac相当陌生,在注入仅具有运行时已知参数的依赖项时遇到了一个问题。 (the code below is an example of the problem I am trying to describe). (下面的代码是我要描述的问题的示例)。

Here is where I setup my container (which gets called in Global.asax) 这是我设置容器的地方(在Global.asax中被调用)

public class Bootstrapper
{
    public static void Config()
    {
        var builder = new ContainerBuilder();
        builder.RegisterControllers(Assembly.GetExecutingAssembly());

        builder.RegisterType<PersonService>().As<IPersonService>().InstancePerHttpRequest();
        builder.RegisterType<PersonRepository>().As<IPersonRepository>().InstancePerHttpRequest();

        IContainer container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
}

Here are the types. 这些是类型。

public class PersonService : IPersonService
{
    private readonly IPersonRepository _repository;

    public PersonService(IPersonRepository repository)
    {
        _repository = repository;
    }

    public Person GetPerson(int id)
    {
        return _repository.GetPerson(id);
    }
}

public interface IPersonRepository
{
    Person GetPerson(int id);
}

public class PersonRepository : IPersonRepository
{
    private readonly int _serviceId;

    public PersonRepository(int serviceId)
    {
        _serviceId = serviceId;
    }

    public Person GetPerson(int id)
    {
        throw new System.NotImplementedException();
    }
}

Then the controller takes the PersonService in the constructor 然后,控制器在构造函数中使用PersonService

 public class HomeController : Controller
{
    private readonly IPersonService _service;

    public HomeController(IPersonService service)
    {
        _service = service;
    }

    public ActionResult Index()
    {
        return View();
    }

}

Obviously this will fall over due to the container expecting the ServiceId argument on the constructor of PersonRepository with the following exception "Cannot resolve parameter 'Int32 serviceId'" 显然,由于容器在PersonRepository的构造函数上期望ServiceId参数而出现以下异常“无法解析参数'Int32 serviceId'”,因此将失败

I can get the serviceId once I know HttpContext.Request.Current.Url, however this is not known at the time of creating the Container. 我知道HttpContext.Request.Current.Url后就可以获取serviceId,但是在创建Container时尚不知道。

I have looked at many articles, forums etc but don't seem to be getting anywhere. 我看过很多文章,论坛等,但似乎什么都没有。

Could anyone point me in the right direction. 谁能指出我正确的方向。 Your help will be much appreciated. 您的帮助将不胜感激。

Thanks 谢谢

I know you use autofac but in our project we use Unity and it definitely can insert primitive types to type registration like this: 我知道您使用autofac,但在我们的项目中我们使用Unity,它肯定可以插入原始类型来键入注册,如下所示:

container.RegisterTypeWithParams<INewsRepository, NewsRepository>("ConnectionString", typeof(ILoggedUser));

Look at this 这个

In general, you don't want to do this as you've modeled it (your PersonRepository). 通常,您不希望对它建模(您的PersonRepository)。 DI is used to resolve service dependencies, and what you have is a stateful component. DI用于解决服务依赖性,而您拥有的是有状态组件。

The way to model this is to use an abstract factory. 对此建模的方法是使用抽象工厂。 Mark Seemann has an excellent blog post on this exact subject. 马克·西曼(Mark Seemann)在这个确切的主题上有一篇很棒的博客文章

As you noted in your comment, passing the value via method injection is also an option, but can be ugly if it needs to be passed down through multiple dependencies. 正如您在注释中指出的那样,通过方法注入传递值也是一种选择,但是如果需要通过多个依赖关系向下传递值,则可能很难看。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM