c# - 仅在生命周期匹配时解析组件

标签 c# .net autofac

接线示例:

// Module 1
builder.Register(ctx => new ServiceImpl1())
       .As<ISomeSubService>()
       .SingleInstance();

// Module 2
builder.Register(ctx => new MyComponent(ctx.Resolve<ISomeSubService>()))
       .As<IComponent>()
       .SingleInstance();

这是一个有效但危险的解决方案:如果稍后有人重构模块 1 并决定使用 ServiceImpl2(它可能不再是 SingleInstance-registrable),模块 2 将默默地引入一个错误。

如果 ctor 参数 ISomeSubService 的解析至少没有相同的生命周期,是否有可能 IComponent 的解析失败?

最佳答案

Autofac 无法强制子依赖项的生命周期等于使用组件的生命周期。

如果您考虑一下,在很多情况下这实际上可能不是错误。

例如,我有一个全局记录器。我可能会将其注册为 SingleInstance因为它可以共享。

builder.RegisterType<MyLogger>()
       .As<ILogger>()
       .SingleInstance();

然后我可能会有一个需要记录器的 MVC Controller 。它只为一次请求而存在。

builder.RegisterType<MyController>()
       .InstancePerRequest();

没关系。记录器应该跨事物共享,因此拥有不同的生命周期就好了。

现在切换一下 - 假设您有一个存储库,可以调用以从数据库获取本地化资源。它的创建成本低廉,并且已注册 InstancePerDependency .

builder.RegisterType<MyResourceRepository>()
       .As<IResourceRepository>();
       .InstancePerDependency();

您在 Windows 窗体应用程序中也有一个显示小部件,它显示一些本地化数据,但它在应用程序的生命周期内有效 - 它是 SingleInstance .

builder.RegisterType<MyWidget>()
       .SingleInstance();

它会在构建时获取资源存储库的副本,并且该资源存储库实例将在整个应用程序生命周期内保存它。 这不一定是错误。在许多情况下,这实际上可能很好。

与其尝试跨模块强制执行,不如让对象控制自己的生命周期,不要太担心它。用它们应该具有的生命周期范围注册事物。

如果您担心单例组件可能会尝试获取不应为整个应用程序保持事件状态的服务, use the Func<T> relationship在单例对象内部自动解析工厂并调用该函数来获取服务而不是卡在它上面。

public class A
{
  Func<B> _b;

  public A(Func<B> b) { _b = b; }

  public void M()
  {
    var b = _b();
    b.DoSomething();
  }
}

您也可以使用 the other implicit relationship types帮助处理此类问题。例如,如果您需要在使用完对象后将其丢弃,您可能需要 Func<Owned<T>>。这样您也可以控制处置。

关于c# - 仅在生命周期匹配时解析组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30896821/

相关文章:

c# - 使用另一个方法作为参数

.net - PowerShell 通用集合

c# - Autofac:将 OnActivated 添加到所有注册

c# - 使用 Autofac 注册通用接口(interface)和类

autofac - Autofac 中的 Lazy<T> 支持发生了什么?

c# - 为什么我的干扰器示例这么慢?

c# - 如何使用 NuGet 打包命令行工具?

c# - 如何在 C# .NET 中读取 HDF5 可变长度字符串属性

c# - 获取所有工作表

c# - 静态异步类的模拟单元测试和依赖注入(inject)