You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Autofac如何注册/解析构造函数含抽象类型参数的类型?

Autofac接口继承场景下的依赖注入问题

问题背景

现有如下类和接口结构:

命令类与抽象基类

Public Class UpdateCommand
  Inherits BaseCommand
  Implements IUpdateCommand

  Public Sub New(Root As DirectoryInfo)
    MyBase.New(Root)
  End Sub
End Class

Public Class CleanCommand
  Inherits BaseCommand
  Implements ICleanCommand

  Public Sub New(Root As DirectoryInfo)
    MyBase.New(Root)
  End Sub
End Class

Public MustInherit Class BaseCommand
  Implements IBaseCommand

  Public Sub New(Root As DirectoryInfo)
    Me.Root = Root
  End Sub

  Protected ReadOnly Property Root As DirectoryInfo Implements IBaseCommand.Root
End Class

Downloader类

Public Class Downloader
  Implements IDownloader

  Public Sub New(Command As IBaseCommand)
    Me.Root = Command.Root
  End Sub

  Private ReadOnly Root As DirectoryInfo Implements IDownloader.Root
End Class

接口定义

Public Interface IUpdateCommand
  Inherits IBaseCommand
End Interface

Public Interface ICleanCommand
  Inherits IBaseCommand
End Interface

Public Interface IBaseCommand
  ReadOnly Property Root As DirectoryInfo
End Interface

Public Interface IDownloader
  ReadOnly Property Root As DirectoryInfo
End Interface

当前注册与解析代码

注册代码:

oRoot = New DirectoryInfo(Options.Root)
oParameters = New List(Of Parameter) From {
  New NamedParameter(NameOf(Options.Root), oRoot)
}

oBuilder = New ContainerBuilder
oBuilder.RegisterType(Of UpdateCommand).As(Of IUpdateCommand).WithParameters(oParameters)
oBuilder.RegisterType(Of CleanCommand).As(Of ICleanCommand).WithParameters(oParameters)
oBuilder.RegisterType(Of Downloader).As(Of IDownloader)()

解析代码:

Dim oUpdateCommand As IUpdateCommand
Dim oCleanCommand As ICleanCommand

Using oScope As ILifetimeScope = Container.BeginLifetimeScope
  oUpdateCommand = oScope.Resolve(Of IUpdateCommand)
  oCleanCommand = oScope.Resolve(Of ICleanCommand)
  oDownloader = oScope.Resolve(Of IDownloader)
End Using

遇到的错误

解析oDownloader时触发错误:

None of the constructors found on type 'VsLayout.Downloader' can be invoked with the available services and parameters:
Cannot resolve parameter 'VsLayout.IBaseCommand Command' of constructor 'Void .ctor(VsLayout.IBaseCommand)'.

尝试将命令类注册为IBaseCommand后,又触发新错误:

Autofac.Core.Registration.ComponentNotRegisteredException
HResult=0x80131500
Message=The requested service 'VsLayout.IUpdateCommand' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

解决方案

方案一:注册命令类时同时关联父接口

Autofac默认不会自动将实现类注册为其接口的父接口,因此需要显式指定命令类同时注册为IBaseCommand和各自的专属接口。修改注册代码如下:

oBuilder.RegisterType(Of UpdateCommand) _
        .As(Of IUpdateCommand) _
        .As(Of IBaseCommand) _
        .WithParameters(oParameters)

oBuilder.RegisterType(Of CleanCommand) _
        .As(Of ICleanCommand) _
        .As(Of IBaseCommand) _
        .WithParameters(oParameters)

注意:如果直接解析IBaseCommand,Autofac会返回最后注册的实现类(此处为CleanCommand)。若需要根据场景注入对应命令,可结合键控服务区分:

' 注册时标记键名
oBuilder.RegisterType(Of UpdateCommand) _
        .Keyed(Of IBaseCommand)("update") _
        .As(Of IUpdateCommand) _
        .WithParameters(oParameters)

oBuilder.RegisterType(Of CleanCommand) _
        .Keyed(Of IBaseCommand)("clean") _
        .As(Of ICleanCommand) _
        .WithParameters(oParameters)

' 注册Downloader时指定注入对应键的服务
oBuilder.RegisterType(Of Downloader).As(Of IDownloader) _
        .WithParameter(ResolvedParameter.ForKeyed(Of IBaseCommand)("update"))

方案二:解析Downloader时手动传入命令实例

若不需要全局注册IBaseCommand,可在解析Downloader时,将已获取的IUpdateCommand/ICleanCommand实例作为参数传入:

Using oScope As ILifetimeScope = Container.BeginLifetimeScope
  oUpdateCommand = oScope.Resolve(Of IUpdateCommand)
  ' 传入已解析的UpdateCommand作为IBaseCommand参数
  oDownloader = oScope.Resolve(Of IDownloader)(New TypedParameter(GetType(IBaseCommand), oUpdateCommand))
End Using

方案三:使用工厂模式动态注入

如果需要根据不同场景自动匹配对应的命令与Downloader,可定义工厂接口并注册:

Public Interface IDownloaderFactory
  Function Create(command As IBaseCommand) As IDownloader
End Interface

' 实现工厂类
Public Class DownloaderFactory
  Implements IDownloaderFactory
  Public Function Create(command As IBaseCommand) As IDownloader Implements IDownloaderFactory.Create
    Return New Downloader(command)
  End Function
End Class

注册工厂:

oBuilder.RegisterType(Of DownloaderFactory).As(Of IDownloaderFactory)()

解析时通过工厂创建Downloader:

Using oScope As ILifetimeScope = Container.BeginLifetimeScope
  oUpdateCommand = oScope.Resolve(Of IUpdateCommand)
  Dim factory = oScope.Resolve(Of IDownloaderFactory)
  oDownloader = factory.Create(oUpdateCommand)
End Using

内容的提问来源于stack exchange,提问作者InteXX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 18:34:56