using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using zero.Core; using zero.Core.Assemblies; using zero.Core.Entities; using zero.Web.Controllers; using zero.Web.Filters; namespace zero.Web { public class ApiControllerFeatureProvider : IApplicationFeatureProvider { IServiceCollection ServiceCollection; public ApiControllerFeatureProvider(IServiceCollection serviceCollection) { ServiceCollection = serviceCollection; } public void PopulateFeature(IEnumerable parts, ControllerFeature feature) { var pagetype = typeof(IPage); var page = ServiceCollection.FirstOrDefault(x => x.ServiceType.Equals(pagetype)); 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 = null; ServiceDescriptor descriptor = ServiceCollection.FirstOrDefault(x => x.ServiceType.Equals(requiredService)); if (descriptor != null) { concreteArgument = descriptor.ImplementationType?.GetTypeInfo(); } if (concreteArgument == null) { IEnumerable concreteArgumentCandidates = AssemblyDiscovery.Current.GetTypes(requiredService, parts); concreteArgument = concreteArgumentCandidates.FirstOrDefault(); if (concreteArgument == null) { isValid = false; break; } } concreteArguments.Add(concreteArgument); } if (!isValid) { continue; } TypeInfo type = candidate.MakeGenericType(concreteArguments.ToArray()).GetTypeInfo(); feature.Controllers.Add(type); } } } }