私が間違っていない場合は、カスタムメタデータプロバイダーをMVCに明示的に登録する必要があります。
ModelMetadataProviders.Current =
new MyMetadataProvider();
このインスタンスをコンテナから解決されるタイプにも注入できるようにする必要がある場合は、コンテナにも登録する必要があります。
ModelMetadataProviders.Current =
new MyMetadataProvider();
container.RegisterSingle<ModelMetadataProvider>(
ModelMetadataProviders.Current);
コンテナに依存関係をカスタムに注入するMyMetadataProvider
場合は、次のようにする必要があります。
container.RegisterSingle<ModelMetadataProvider, MyMetadataProvider>();
container.Verify();
// Call this after you're done configuring the container.
ModelMetadataProviders.Current =
container.GetInstance<ModelMetadataProvider>();
はシングルトンであるため、ModelMetadataProviders.Current
はシングルトンであるModelMetadataProvider
必要があります。少なくとも、アプリケーションの存続期間中キャッシュされ、複数のスレッドから同時にアクセスされることは問題ではありません。カスタムプロバイダーに依存関係を挿入する場合、これはカスタムプロバイダーには適切でない場合があります(これらの依存関係はシングルトンライフスタイルよりもライフタイムが短い可能性があるため)。
その場合、DependencyResolver
:にコールバックするプロキシプロバイダーを作成する必要があります。
public DependencyResolverModelMetadataProvider : ModelMetadataProvider
{
public override IEnumerable<ModelMetadata> GetMetadataForProperties(
object container, Type containerType)
{
return GetProvider().GetMetadataForProperties(
container, containerType);
}
public override ModelMetadata GetMetadataForProperty(
Func<object> modelAccessor, Type containerType, string propertyName)
{
return GetProvider().GetMetadataForProperty(
modelAccessor, containerType, propertyName);
}
public override ModelMetadata GetMetadataForType(
Func<object> modelAccessor, Type modelType)
{
return GetProvider().GetMetadataForType(
modelAccessor, modelType);
}
private static ModelMetadataProvider GetProvider()
{
return (ModelMetadataProvider)
DependencyResolver.Current.GetService(
typeof(ModelMetadataProvider));
}
}
このプロキシは呼び出しDependencyResolver
ごとに呼び出しを行うため(状態は含まれません)、単一のインスタンスを安全に作成してModelMetadataProviders.Current
プロパティに格納できます。
その場合、構成は次のようになります。
// register the proxy that calls back into the container.
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
// Register it as transient.
container.Register<ModelMetadataProvider, MyMetadataProvider>();
カスタムプロバイダーで元のプロバイダーを装飾する場合は、この元のプロバイダーをカスタムプロバイダーのプロパティに挿入する必要があります(他の方法もありますが、これが最も簡単な方法です)。
var original = ModelMetadataProviders.Current;
// register the proxy that calls back into the container.
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
// Register it as transient.
container.Register<ModelMetadataProvider, MyMetadataProvider>();
container.RegisterInitializer<MyMetadataProvider>(prov =>
{
// The decorated provider is put as a property on the
// MyMetadataProvider class.
prov.DecoratedProvider = original;
});
別のアプローチは、カスタムMyMetadataProvider
をデコレータクラスとして登録することです。
container.RegisterSingle<ModelMetadataProvider>(
ModelMetadataProviders.Current);
container.RegisterDecorator(
typeof(ModelMetadataProvider),
typeof(MyMetadataProvider));
ModelMetadataProviders.Current =
new DependencyResolverModelMetadataProvider();
MyMetadataProvider
デコレータとして登録すると、登録された元のファイルにラップされますModelMetadataProvider
(これはに挿入されます。拡張機能を取得するにはプロジェクトMyMetadataProvider
が必要です。SimpleInjector.Extensions.dll
RegisterDecorator