【问题标题】:ASP.Net MVC Constructor Injection with Autofac - Runtime parameters使用 Autofac 的 ASP.Net MVC 构造函数注入 - 运行时参数
【发布时间】:2014-07-18 15:27:10
【问题描述】:

我对 Autofac 相当陌生,并且在注入具有仅在运行时才知道的参数的依赖项时遇到了问题。 (下面的代码是我试图描述的问题的一个例子)。

这里是我设置容器的地方(在 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));
    }
}

这里是类型。

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();
    }
}

然后控制器在构造函数中获取PersonService

 public class HomeController : Controller
{
    private readonly IPersonService _service;

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

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

}

显然这将失败,因为容器在 PersonRepository 的构造函数上期望 ServiceId 参数,并出现以下异常“无法解析参数 'Int32 serviceId'”

知道 HttpContext.Request.Current.Url 后就可以获取 serviceId,但是在创建 Container 时并不知道。

我看过很多文章、论坛等,但似乎没有得到任何结果。

谁能指出我正确的方向。非常感谢您的帮助。

谢谢

【问题讨论】:

    标签: c# asp.net asp.net-mvc dependency-injection autofac


    【解决方案1】:

    我知道你使用 autofac,但在我们的项目中我们使用 Unity,它绝对可以插入原始类型来进行类型注册,如下所示:

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

    this

    【讨论】:

    • 只有在注册时知道该值时才有效。他/她需要一个仅在运行时才知道的值。
    • 感谢您的评论。我将如何在运行时解析参数?我在想我需要以某种方式解决控制器中的依赖关系?
    • 好的,我现在明白了...我认为这不是好方法。使用 IOC 将运行时值发送到创建对象。如果它不是目的。
    • 简我自己也开始这么想了。也许重构依赖关系并向其中一种方法添加参数会是更好的方法。
    • 当然。我认为它更好更常见
    【解决方案2】:

    一般来说,您不希望这样做,因为您已经对其进行了建模(您的 PersonRepository)。 DI是用来解决服务依赖的,你拥有的是一个有状态的组件。

    对此进行建模的方法是使用抽象工厂。 Mark Seemann 在这个确切的主题上有一个excellent blog post

    正如您在评论中所指出的,通过方法注入传递值也是一种选择,但如果需要通过多个依赖项传递值可能会很难看。

    【讨论】:

    • 好的,谢谢,我去看看那篇文章。我以为某处有一点气味。我实际上遇到问题的代码是在我的团队采用 DI 和 TDD 之前构建的,并且是在运行时更新的!可能是重构的时候了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多