Ich erkannte schließlich, dass Modellbinder von Modellbinder-Anbietern, nicht über Abhängigkeitsinjektion erhalten werden. Um meine FooModelBinder
instanziieren, muss ich eine FooModelBinderProvider
erstellen. Und um eine Instanz von ComplexTypeModelBinder
für die Komposition zu erhalten, benötigt mein Provider Zugriff auf eine ComplexTypeModelBinderProvider
. Mit anderen Worten: Um über einen Modellbinder zu komponieren, müssen Sie auch einen Modellbinderanbieter erstellen.
Hier ist der Anbieter. Beachten Sie, dass wir nicht den genauen Typ des injizierten Providers angeben müssen, da wir einfach die vorhandene Funktionalität eines anderen Modellbinders umschließen.
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;
}
}
Und hier ist der Binder. Beachten Sie, dass das erste, was wir in BindModelAsync
tun, ist Trampolin in den Ordner "Arbeiter".
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
}
}
Schließlich ist hier, wie die benutzerdefinierten Binder registrieren:
services.AddMvc(options =>
{
var workerProvider = options.ModelBinderProviders.First(p => p.GetType() == typeof(ComplexTypeModelBinderProvider));
options.ModelBinderProviders.Insert(options.ModelBinderProviders.IndexOf(workerProvider), new FooModelBinderProvider(workerProvider));
})