I'm struggling to access a service when configuring a factory function in our app setup.
We're using Asp.Versioning, and I'm trying to inject a service for use in our custom model builder.
Here is the relevant configuration section
builder.Services.AddSingleton(Of EdmTypeReplacer)
builder.Services.AddApiVersioning() _
.AddMvc() _
.AddOData(Sub(o)
o.ModelBuilder.OnModelCreated = Sub(modelBuilder, model)
' I want to use my injected EdmTypeReplacer here.
' Not a static class instance (which I'm using currently)
Dim replacer = EdmTypeReplacer.Instance
replacer.OnModelCreated(model)
End Sub
o.ModelBuilder.ModelBuilderFactory = Function()
' I want to use my injected EdmTypeReplacer here.
' Not a static class instance (which I'm using currently)
Dim replacer = EdmTypeReplacer.Instance
Return New CustomConventionODataModelBuilder(replacer)
End Function
End Sub) _
.AddODataApiExplorer()
I'm trying to inject a singleton EdmTypeReplacer
into CustomConventionODataModelBuilder
, but I can't pass a service to the ModelBuilderFactory
Function
params because it is expecting an empty function delegate.
I need access to the same instance of EdmTypeReplacer
in the delegate for OnModelCreated
too.
I'm not sure how/whether I can access the ServiceProvider
as it's still being built.
I've currently been forced to create EdmTypeReplacer
as a static class singleton instance and use that, but I'm convinced there must be a way to inject this, or at least access the ServiceProvider
in the factory function.
Feel free to give any answers in C# instead of VB, if you're more familiar with that.
*** Additional info ***
CustomConventionODataModelBuilder
configures EdmTypeReplacer
with changes which are used later on when OnModelCreated
is called. So, it is necessary for both to use the same instance (ideally a singleton instance, as reflection is used in this process).
@Brando Zhang's answer got me on the right track.
We can capture an instance of EdmTypeReplacer
and then pass this instance directly to the OnModelCreated
and ModelBuilderFactory
functions. The same instance is then returned in the AddSingleton
factory method so all classes get the same instance, instead of a duplicate instance when IServiceProvider is actually built.
This avoids us needing to create a partially completed service provider using builder.Services.BuildServiceProvider()
as we already have a reference to the instance we need in the same scope.
Dim replacer = new EdmTypeReplacer
builder.Services.AddSingleton(Of EdmTypeReplacer)(Function(s) replacer)
builder.Services.AddApiVersioning() _
.AddMvc() _
.AddOData(Sub(o)
o.ModelBuilder.OnModelCreated = Sub(modelBuilder, model)
replacer.OnModelCreated(model)
End Sub
o.ModelBuilder.ModelBuilderFactory = Function()
Return New CustomConventionODataModelBuilder(replacer)
End Function
End Sub) _
.AddODataApiExplorer()