2017-12-04 9 views
0

特定のクラスFooのモデルバインディングをカスタマイズする必要があります。これは、いくつかの追加の後処理(通常、条件付きで空のコレクションフィールドを空のコレクションに設定する)で通常のバインディングロジックを拡張することです。このロジックをモデル結合に追加して、結果がアクションフィルタなどで利用できるようにします。ComplexTypeModelBinderを拡張する方法

最も直接的なアプローチは、ComplexTypeModelBinderから派生し、BindModelAsyncを上書きすることです。しかし、その方法は残念ながら仮想ではありません。

次の代替構成は次のとおりです。私はComplexTypeModelBinderのインスタンスを持っている、または取得しているFooModelBinderクラスを作成しようとしています。しかし、私はComplexTypeModelBinderを注入または解決する方法を理解できません。これは可能ですか? ComplexTypeModelBinderの機能を拡張するためのより良い方法はありますか?

答えて

0

モデルバインダーは、モデルバインダープロバイダから、依存性注入を介してではなく、取得されることがわかりました。 FooModelBinderを正しくインスタンス化するには、FooModelBinderProviderを作成する必要があります。そして、構成のためにComplexTypeModelBinderのインスタンスを適切に取得するには、私のプロバイダはComplexTypeModelBinderProviderにアクセスする必要があります。つまり、モデルバインダーを使用して構成するには、モデルバインダープロバイダーを使用して構成する必要があります。

ここはプロバイダです。注入されたプロバイダの正確な型を指定する必要はないことに注意してください。これは、単に別のモデルバインダの既存の機能をラッピングするためです。

public class FooModelBinderProvider : IModelBinderProvider 
{ 
    private readonly IModelBinderProvider workerProvider; 

    public FooModelBinderProvider(IModelBinderProvider workerProvider) 
    { 
    this.workerProvider = workerProvider; 
    } 

    public IModelBinder GetBinder(ModelBinderProviderContext context) 
    { 
    if (context == null) 
    { 
     throw new ArgumentNullException(nameof(context)); 
    } 

    if (context.Metadata.ModelType == typeof(Foo)) 
    { 
     return new FooModelBinder(this.workerProvider.GetBinder(context)); 
    } 

    return null; 
    } 
} 

ここにバインダーがあります。我々がBindModelAsyncで行う最初のことは、 "作業者"バインダーへのトランポリンであることに注意してください。

public class FooModelBinder : IModelBinder 
{ 
    private readonly IModelBinder worker; 

    public FooModelBinder(IModelBinder worker) 
    { 
    this.worker = worker; 
    } 

    public async Task BindModelAsync(ModelBindingContext bindingContext) 
    { 
    await this.worker.BindModelAsync(bindingContext); 
    if (!bindingContext.Result.IsModelSet) 
    { 
     return; 
    } 

    var foo = bindingContext.Result.Model as Foo; 
    if (foo == null) 
    { 
     throw new InvalidOperationException($"Expected {bindingContext.ModelName} to have been bound by ComplexTypeModelBinder"); 
    } 

    // NOW DO SOME INTERESTING POST-PROCESSING 
    } 
} 

は最後に、ここではカスタムバインダを登録する方法は次のとおりです。

services.AddMvc(options => 
    { 
    var workerProvider = options.ModelBinderProviders.First(p => p.GetType() == typeof(ComplexTypeModelBinderProvider)); 
    options.ModelBinderProviders.Insert(options.ModelBinderProviders.IndexOf(workerProvider), new FooModelBinderProvider(workerProvider)); 
    }) 
関連する問題