データアクセス用のリポジトリを備えた WebAPI + Autofac + Automapper を使用しています。モデルをドメイン エンティティにマップする必要があります。具体的には、ID 値を実際のエンティティに変換する必要があります。大したことではありませんよね?私はこれを MVC で問題なく実行しました。本質を明らかにするために、私がやっていることを単純化します。
public class EntityConverter<T> : ITypeConverter<int, T>
where T : Entity
{
public EntityConverter(IRepository<T> repository)
{
_repository = repository;
}
private readonly IRepository<T> _repository;
public T Convert(ResolutionContext context)
{
_repository.Get((int) context.SourceValue);
}
}
リポジトリは Autofac に登録されInstancePerApiRequest
、セッション/トランザクション管理のため、リポジトリとして管理されます。したがって、コンバーターを同じスコープに登録する必要があります。
builder.RegisterGeneric(typeof(EntityConverter<>))
.AsSelf()
.InstancePerApiRequest();
Automapper の設定は次のようになります。
var container = builder.Build(); // build the Autofac container and do what you will
Mapper.Initialize(cfg => {
cfg.ConstructServicesUsing(container.Resolve); // nope nope nope
// configure mappings
cfg.CreateMap<int, TestEntity>().ConvertUsing<EntityConverter<TestEntity>>()
});
Mapper.AssertConfigurationIsValid();
だからここが悪い部分です。Automapper では、ConstructServicesUsing
config をビルドする前に、guy を設定する必要があることを理解しています。後で設定すると、使用されなくなります。container
がルート スコープであるため、上記の例は機能しません。解決しようとするEntityConverter<TestEntity>
と、Autofac は、要求された型が別のスコープに登録されていると不平を言います。理にかなっています。WebApi によって作成されたスコープが必要です。
少し間を置いて、WebApi の依存性注入に関する 1 つの事実を説明させてください (これは Autofac 固有のものではないと思います)。WebApi はIDependencyScope
リクエストの を作成し、HttpRequestMessage.Properties
. HttpRequestMessage
同じインスタンスにアクセスできない限り、元に戻すことはできません。したがって、私のAsInstancePerApiRequest
スコープIRepository
と私のコンバーターはそれに依存していIDependencyScope
ます。
つまり、それこそが問題の本質であり、私は MVC とのこの違いに本当に不満を感じていました。あなたはできません
cfg.ConstructServicesUsing(GlobalConfiguration.Configuration.DependencyResolver.GetService);
を使用するのと同じcontainer.Resolve
です。使えない
GlobalConfiguration.Configuration.DependencyResolver.BeginScope().GetService
A)実際に必要なスコープの隣に新しいスコープを作成するため、B)作成した新しいスコープを実際にクリーンアップできないからです。Service Locator の使用は、同じ問題を解決するための新しい方法です。WebApi が使用しているスコープに到達できません。私のコンバーターとその依存関係が単一のインスタンスまたは依存関係ごとのインスタンスである場合、それは問題にはなりませんが、そうではなく、それを変更すると、さらに多くの問題が発生します。
これで、Autofac を使用して AutoMapper 構成を作成し、それを単一のインスタンスとして登録できます。リクエストごとのIMappingEngine
インスタンスを作成することもできます。しかし、サービス コンストラクターが、現在のスコープにアクセスできない、最初に登録した単一のデリゲートを常に使用する場合、それは私には何の役にも立ちません。マッピング エンジンのインスタンスごとにデリゲートを変更できれば、うまくいくかもしれません。しかし、私はできません。
それで、私は何ができますか?