using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Controllers; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using zero.Core; using zero.Core.Assemblies; using zero.Web.Controllers; using zero.Web.Filters; namespace zero.Web { public class ApiControllerFeatureProvider : IApplicationFeatureProvider { public ApiControllerFeatureProvider() { } public void PopulateFeature(IEnumerable parts, ControllerFeature feature) { IEnumerable candidates = AssemblyDiscovery.Current.GetTypes(parts, true).Where(x => x.ContainsGenericParameters); foreach (TypeInfo candidate in candidates) { Type genericType = candidate.GetGenericTypeDefinition(); Type[] genericArguments = genericType.GetGenericArguments(); List concreteArguments = new List(); bool isValid = true; foreach (Type arg in genericArguments) { Type requiredService = arg.GetInterfaces().FirstOrDefault(); if (requiredService == null) { isValid = false; break; } TypeInfo concreteArgument = AssemblyDiscovery.Current.GetTypes(requiredService, parts).FirstOrDefault(); if (concreteArgument == null) { isValid = false; break; } concreteArguments.Add(concreteArgument); } if (!isValid) { continue; } TypeInfo type = candidate.MakeGenericType(concreteArguments.ToArray()).GetTypeInfo(); feature.Controllers.Add(type); } } } }