I have the following code for operation filter that helps me serialize arrays then sends it to a FromForm binder, how I turned it generic so I can get several class types and pass it over as T type to the following class so I wrote this:
public class ArraySettingsOperationFilter<T> where T : IOperationFilter, new()
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.RequestBody != null && operation.RequestBody.Content.TryGetValue("multipart/form-data", out var openApiMediaType))
{
var options = new JsonSerializerOptions { WriteIndented = true };
var array = new OpenApiArray
{
new OpenApiString(JsonSerializer.Serialize(new T(),options)),
};
openApiMediaType.Schema.Properties["Competences"].Example = array;
}
}
}
on startup class i'm getting every class that is marked by an interface and pass them over to operationfilter within Swagger generator settings:
var types = typeof(IMarkerInterface)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(IMarkerInterface)) && !t.IsAbstract)
.Select(t => Activator.CreateInstance(t) as IMarkerInterface).ToList();
then:
services.AddSwaggerGen(c =>
{
foreach (var type in types)
{
c.OperationFilter<ArraySettingsOperationFilter<type>>(); //however here error says type is a variable but used like a type.
}
});
Anyone has a clue how to fix this issue? Or a workaround?
Well, c.OperationFilter<T>
is just a generic extension method that adds FilterDescriptor
s to OperationFilterDescriptors
list. So you don't have to rely on that generic method. A few modifications like the below will get you there:
First change your generic
ArraySettingsOperationFilter
to a class that accepts a type in the constructor
public class ArraySettingsOperationFilter : IOperationFilter
{
private readonly Type type;
public ArraySettingsOperationFilter(Type type)
{
// you can check this type implements the interface here
this.type = type;
}
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.RequestBody != null && operation.RequestBody.Content.TryGetValue("multipart/form-data", out var openApiMediaType))
{
var options = new JsonSerializerOptions { WriteIndented = true };
var array = new OpenApiArray
{
new OpenApiString(JsonSerializer.Serialize(Activator.CreateInstance(this.type),options)),
};
openApiMediaType.Schema.Properties["Competences"].Example = array;
}
}
}
Make
FilterDescriptor
s from the marked classes
var filterDescriptors = typeof(IMarkerInterface)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(IMarkerInterface)) && !t.IsAbstract)
.Select(r => new FilterDescriptor { Type = typeof(ArraySettingsOperationFilter), Arguments = new object[] { r } })
.ToArray();
// Arguments array will be used for instantiating ArraySettingsOperationFilter
Configure Swaggergen
builder.Services.AddSwaggerGen(c => c.OperationFilterDescriptors.AddRange(filterDescriptors));
Edit
You may skip instantiating ArraySettingsOperationFilter
if your marked types do the same thing.
var filterDescriptors = typeof(IMarkerInterface)
.Assembly.GetTypes()
.Where(t => t.IsSubclassOf(typeof(IMarkerInterface)) && !t.IsAbstract)
.Select(r => new FilterDescriptor { Type = r } )
.ToArray();