This is a (to me) pretty weird problem, because it was already running perfectly but went completely south after some unrelated changes.
I’ve got a Repository which imports in its constructor a list of IExtensions via Autofacs MEF integration. One of these extensions contains a backreference to the Repository as Lazy(Of IRepository) (lazy because of the circular reference that would occur).
But as soon as I try to use the repository, Autofac throws a ComponentNotRegisteredException with the message "The requested service ‘ContractName=Assembly.IRepository()’ has not been registered."
That is, however, not really correct, because when I break right after the container-build and explore the list of services, it’s there – Exported() and with the correct ContractName.
I’d appreciate any help on this…
Michael
[Edit] Here’s a thinned-out version of the code:
Repository
Public Class DocumentRepository
Implements IDocumentRepository
Private _extensions As IEnumerable(Of IRepositoryExtension)
Public Sub New(ByVal extensions As IEnumerable(Of IRepositoryExtension))
_extensions = extensions
End Sub
Public Sub AddDocument(ByVal document As Contracts.IDocument) Implements Contracts.IDocumentRepository.AddDocument
For Each extension In _extensions
extension.OnAdded(document.Id)
Next
End Sub
End Class
Plugin
<Export(GetType(IRepositoryExtension))>
<PartCreationPolicy(ComponentModel.Composition.CreationPolicy.Shared)>
Public Class PdfGenerator
Implements IRepositoryExtension
Private _repositoryFactory As Lazy(Of IDocumentRepository)
Public Sub New(ByVal repositoryFactory As Lazy(Of IDocumentRepository))
_repositoryFactory = repositoryFactory
End Sub
Public Sub CreatePdf(ByVal id As Guid) Implements Contracts.IRepositoryExtension.OnAdded
Dim document = _repositoryFactory.Value.GetDocumentById(id)
End Sub
End Class
Bootstrapper
Public Class EditorApplication
Inherits System.Web.HttpApplication
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Dim builder As New ContainerBuilder()
Dim catalog1 As New TypeCatalog(GetType(DataRepositoryScheme))
Dim catalog2 As New DirectoryCatalog(HttpContext.Current.Server.MapPath("/Plugins"))
builder.RegisterComposablePartCatalog(New AggregateCatalog(catalog1, catalog2))
builder.RegisterType(Of DocumentRepository).As(Of IDocumentRepository).SingleInstance().Exported(Function(x) x.As(Of IDocumentRepository)())
AutofacServiceHostFactory.Container = builder.Build()
End Sub
End Class
Ah immediately after I posted that last comment I think I figured it out:
Note that there is a pair of parentheses after the contract name – this is because the contract is a function, i.e., this message was produced by the following constructor, which is slightly different from the one in your sample:
Note the ‘Func’ in there. MEF, unlike Autofac, does not regard Func as a special type and so will not translate this into the same contract as for Lazy.
If you want to provide a Func to a MEF component, you need to export it as a Func from Autofac. This is a bit tricky:
You may need to play with the syntax a bit, my VB.NET is fairly shaky.
My guess is that there are stale binaries in your /Extensions directory that are interfering with debugging this.
Hope this is on the mark!
Nick