0

ReadModelRepository使い捨てクラスのインスタンスに依存する (しかし所有していない)非使い捨てクラスがありますReadModelDbContext。内で、オブジェクトが作成されたときにのみ解決さModuleれるように (依存関係ごとに 1 つのインスタンス)、Autofac 3.0.2 コンテナーを構成したいと考えています。ReadModelDbContextReadModelRepository

これは私が現在持っているものです:

builder.RegisterType<ReadModelRepository>().As<IReadModelRepository>();
builder.Register(c => new ReadModelDbContext(_connectionStringName)).AsSelf();

ReadModelDbContextただし、モジュールによって提供される登録を使用して、任意のクラスを解決できるようにしたくありません。ReadModelDbContext実際、他のクラスが異なるインスタンスを解決する必要がある可能性があります。

これを解決するにはWithParameter、次のスニペットのように を使用できます。

builder
    .RegisterType<ReadModelRepository> ().As<IReadModelRepository> ()
    .WithParameter (
        (p, c) => p.ParameterType == typeof (ReadModelDbContext), 
        (p, c) => new ReadModelDbContext (_connectionStringName));

ReadModelDbContextただし、を解決する有効期間スコープReadModelRepository(または実際にはその解決コンポーネントの有効期間) が終了したときに、Autofac が自動的に破棄する必要もあります。を使用するWithParameterと、これは機能しないようです。

Disposeしたがって、本質的には、最も外側のコンポーネントの有効期間のスコープが終了したときに呼び出されるように、外側のコンポーネントのコンテキストでのみ依存関係を登録したいと思います。これは可能ですか?

4

3 に答える 3

1

多分、これはあなたを助けるでしょう。

public class RepositoryManager : IDisposable
{
    private ILifetimeScope m_RootLifetimeScope;
    private ILifetimeScope m_RepositoryScope;
    private bool m_Disposed;

    public RepositoryManager(ILifetimeScope rootLifetimeScope)
    {
        m_RootLifetimeScope = rootLifetimeScope;
    }

    public IReadModelRepository CreateReadModelRepository()
    {
        m_RepositoryScope = m_RootLifetimeScope.BeginLifetimeScope(
                builder =>
                    {
                        builder.RegisterType<ReadModelRepository>().As<IReadModelRepository>();
                        builder.Register(c => new ReadModelDbContext(_connectionStringName)).AsSelf();
                    });
        return m_RepositoryScope.Resolve<IReadModelRepository>();
    }

    public void Dispose()
    {
        if (m_Disposed) return;

        m_RepositoryScope.Dispose(); //ReadModelDbContext will be disposed

        m_Disposed = true;
    }
}

//registration
builder.RegisterType<RepositoryManager>().InstancePerDependency();

//using
using (var repositoryManager = yourContainer.Resolve<RepositoryManager>())
{
    IReadModelRepository repository = repositoryManager.CreateReadModelRepository();
}
于 2013-07-05T03:22:42.707 に答える
0

ReadModelRepositoryに依存することをお勧めしFunc<Owned<ReadModelDBContext>>ます。

何かのようなもの:

using Autofac.Features.OwnedInstances;

class ReadModelRepository : IReadModelRepository
{
    public ReadModelRepository(Func<Owned<ReadModelDBContext>> contextFactory)
    {
        _ctxFactory = contextFactory;
    }

    public DoSomethingUseful()
    {
        using (var context = _ctxFactory())
        {
            // use context.Value in here;
            // it will be disposed when exiting the block
            ...
        }
    }

    private readonly Func<Owned<ReadModelDBContext>> _ctxFactory;
}

次に、必要に応じて ReadModelRepository と ReadModelDBContext を登録できます。

このアプローチでは、他のクラスが を解決できないという問題は解決しませんReadModelDBContextが、. 型に到達できない場合、コンテナーからインスタンスを要求することはできません。IReadModelRepository

Autofac Wiki には、このアプローチに関するドキュメントがいくつかあります。

于 2013-07-25T21:03:45.847 に答える
0

しばらくして、実際には別のアプローチを採用しました。内部コンポーネント ( ReadModelDbContext) を秘密鍵に登録します。

var privateKey = new object();
builder.Register(c => new ReadModelDbContext(_connectionStringName)).Keyed<ReadModelDbContext>(privateKey);
builder.Register(ctx => new ReadModelRepository(ctx.ResolveKeyed<ReadModelDbContext>(privateKey))).As<IReadModelRepository>();

他の誰もキーを持っていないため、これにより事実上、ReadModelDbContext登録が に対して非公開になりReadModelRepositoryます。

于 2014-05-22T06:52:30.303 に答える