2

これは (私にとって) かなり奇妙な問題です。なぜなら、それはすでに完全に実行されていたのに、いくつかの無関係な変更の後で完全に南下してしまったからです。

Autofacs MEF統合Repositoryを介してコンストラクターにリストをインポートする があります。IExtensionsこれらの拡張機能の 1 つにRepositoryasへの後方参照が含まれていますLazy(Of IRepository)(循環参照が発生するため遅延)。

しかし、リポジトリを使用しようとするとすぐに、Autofac はComponentNotRegisteredException「要求されたサービス 'ContractName=Assembly.IRepository()' は登録されていません。」というメッセージをスローします。

ただし、これは実際には正しくありません。なぜなら、コンテナー ビルドの直後にブレークしてサービスのリストを調べると、Exported() と正しい ContractName がそこにあるからです。

これについて何か助けていただければ幸いです...
マイケル

[編集] 以下は、コードを間引いたバージョンです。

リポジトリ

Public クラス DocumentRepository
    IDocumentRepository を実装します

    IEnumerable としてのプライベート _extensions (IRepositoryExtension の)
    
    Public Sub New(ByVal extensions As IEnumerable(Of IRepositoryExtension))
        _extensions = 拡張子
    サブ終了

    Public Sub AddDocument(ByVal document As Contracts.IDocument) Contracts.IDocumentRepository.AddDocument を実装します
        For Each extension In _extensions
            extension.OnAdded(document.Id)
        次
    サブ終了
クラス終了

プラグイン

<Export(GetType(IRepositoryExtension))>
<PartCreationPolicy(ComponentModel.Composition.CreationPolicy.Shared)>
パブリック クラス PdfGenerator
    IRepositoryExtension を実装します

    Private _repositoryFactory を Lazy として (IDocumentRepository の)
    
    Public Sub New(ByVal repositoryFactory As Lazy(Of IDocumentRepository))
        _repositoryFactory = リポジトリファクトリー
    サブ終了

    Public Sub CreatePdf(ByVal id As Guid) は Contracts.IRepositoryExtension.OnAdded を実装します
        Dim ドキュメント = _repositoryFactory.Value.GetDocumentById(id)
    サブ終了
クラス終了

ブートストラップ

パブリック クラス EditorApplication
    System.Web.HttpApplication を継承

    Sub Application_Start (オブジェクトとしての ByVal 送信者、EventArgs としての ByVal e)
        Dim ビルダー As New ContainerBuilder()
        
        Dim catalog1 As New TypeCatalog(GetType(DataRepositoryScheme))
        Dim catalog2 As New DirectoryCatalog(HttpContext.Current.Server.MapPath("/Plugins"))
        builder.RegisterComposablePartCatalog(新しい AggregateCatalog(catalog1, catalog2))
        
        builder.RegisterType(Of DocumentRepository).As(Of IDocumentRepository).SingleInstance().Exported(Function(x) x.As(Of IDocumentRepository)())
        
        AutofacServiceHostFactory.Container = builder.Build()
    サブ終了
クラス終了
4

1 に答える 1

1

ああ、最後のコメントを投稿した直後に、私はそれを理解したと思います:

The requested service 'ContractName=ConsoleApplication7.IDocumentRepository()'
has not been registered.

コントラクト名の後に 1 対の括弧があることに注意してください。これは、コントラクトが関数であるためです。つまり、このメッセージは次のコンストラクターによって生成されたものであり、サンプルのものとは少し異なります。

Public Sub New(ByVal repositoryFactory As Func(Of IDocumentRepository))
    _repositoryFactory = repositoryFactory
End Sub

そこにある「Func」に注意してください。MEF は、Autofac とは異なり、Func を特別な型とは見なさないため、これを Lazy と同じコントラクトに変換しません。

Func を MEF コンポーネントに提供する場合は、それを Autofac から Func としてエクスポートする必要があります。これは少しトリッキーです:

builder.RegisterType(Of DocumentRepository).As(Of IDocumentRepository)

builder.Register(Function(c) c.Resolve(Of Func(Of IDocumentRepository))) _
    .As(New UniqueService()) _
    .Exported(Function(x) x.As(Of Func(Of IDocumentRepository))

構文を少しいじる必要があるかもしれませんが、私の VB.NET はかなり不安定です。

私の推測では、これをデバッグするのを妨げている古いバイナリが /Extensions ディレクトリにあると思います。

これが的を射ていることを願っています!

ニック

于 2010-06-12T21:46:16.457 に答える