3

モデルメタデータプロバイダーを単純なインジェクターに登録しようとするとエラーは発生しませんが、インスタンスにアクセスすると、デフォルトでmvcにインスタンスが表示されます。

単純なインジェクターを登録しようとしている方法は次のとおりです。

public static class SimpleInjectorInitializer{
    public static void Initialize(){
        var container = new Container(new ContainerOptions AllowOverridingRegistrations = true});
        InitializeContainer(container);
        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
        container.RegisterMvcAttributeFilterProvider();
        container.Verify();
        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    }
    private static void InitializeContainer(Container container){   
        container.Register<ModelMetadataProvider, MyMetadataProvider>();
    }

}

4

1 に答える 1

7

私が間違っていない場合は、カスタムメタデータプロバイダーを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.dllRegisterDecorator

于 2012-08-15T07:23:50.927 に答える