【问题标题】:How to instantiate outside of a constructor?如何在构造函数之外实例化?
【发布时间】:2018-07-26 11:15:55
【问题描述】:

如何用 Autofac 语法复制这段代码?

public static class MenuConfig
    {
        public static void Initialize()
        {
            var _menuService = DependecyFactory.GetInstance<IMenuService>(); 
            Parameters.Menu = _menuService.Menu();
        }
    }

在称其为“重复问题”之前,请注意我正在寻找 Autofac 命令。我不能在任何地方注入接口,然后调用“Resolve”。我需要做的是内联和未注入的“InstancePerRequest”,所以我不必这样做:

var _service = new Service(new Dependency(new context()));

LightInject 有一个方法允许从构造函数的接口 OUTSIDE 进行实例化,如下所示:

var _service = DependecyFactory.GetInstance<IService>();

Autofac的等效方法是什么?

【问题讨论】:

  • 更具体地说明您要做什么...
  • 构造函数之外是什么意思?你有一个构造函数,我想?而且你正在学习的课程可以在 Autofac 上注册,对吧?
  • 这是一个边缘情况。我有一个静态类,在启动时需要数据库数据。我无法实例化静态类,因此我需要一种从我的服务中获取数据的方法。使用 LightInject,这很容易。我如何对 Autofac 做同样的事情?
  • 你不能把那个静态类改成非静态类,然后注册为单例吗?

标签: c# autofac


【解决方案1】:

当调用containerBuilder.Build() 时,你会得到一个实现IContainerILifetimeScope 的容器,只要你获得这些接口之一,就可以从中解析类型:

container.Resolve<IService>();

如果您希望此容器是静态的,您可以将容器作为静态属性添加到 ProgramStartup 类(取决于您是创建控制台还是 ASP.NET 应用程序)。

请记住,根容器将在您的应用程序的整个持续时间内都存在,因此如果使用不当,可能会导致不必要的内存泄漏。另请参阅documentation 中的警告。

不过,完全可以通过从您的界面解析Owned&lt;&gt; 版本来自己进行内存管理:

using (var service = Program.Container.Resolve<Owned<IService>>())
{
    service.Value.UseService();
}

无论如何,既然您在 cmets 中提到了一个静态类,最好的解决方案是将其更改为非静态类并将其注册为 Autofac 的单例。然后,您可以将Func&lt;Owned&lt;IService&gt;&gt; serviceFactory 注入到该单例中,并在您需要的任何地方创建/处置服务实例。

using (var service = serviceFactory())
{
    service.Value.UseService();
}

【讨论】:

  • 正如the documentation 中提到的,您不应该直接从根容器中解析。
  • 是的,需要注意这个 idd。但是,创建一个在程序期间存在的生命周期并不能解决这个问题,因此需要使用其他解决方案。我已经更新了我的答案。
  • 所以底线:没有等效的 Autofac 命令来执行 LightInject 的操作,对吗?我简要地研究了单例模式,但无法完全掌握和实现它。我将对此进行更多研究,因为我认为这是正确的方法。 LightInject 方法快速简单,对于这些类型的场景非常有用。我希望我不必用 Autofac 重新设计原始代码。
  • 好吧,将来你会知道要避免将静态类与 DI 结合使用,一个全新的世界将会打开(例如,单元测试,使用静态类 + LightInject 可能是不可能的)。
  • 顺便说一句,您不需要查找单例模式。我的意思只是一个非静态类,您使用 Autofac 注册 AsSingleton(作为静态类的替代品)。
【解决方案2】:

Autofac 根本不可能做到这一点。所有其他涉及 Autofac 的解决方案都需要代码重构,这可能会破坏软件功能。所以不幸的是,最优雅且破坏性最小的解决方案是:

var _service = new Service(new Dependency(new context()));

由于这是仅解决软件一部分的边缘情况,因此这种折衷方案是可以接受的。不过,如果 Autofac 在未来的某个版本中实现此功能,那就太好了。

【讨论】:

    猜你喜欢
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    • 2018-02-20
    • 2011-05-08
    • 2019-07-16
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多