Support per process caching of controller discovery
Scan only relevant (non skipped) assemblies FinalizeSetup point, to make "stuff" immutable Support controllers under any namespace support customizing controller discovery support customizing skipped assemblies support customizing multiple controllers with the same name under different namespaces and assemblies support controller ambiguity detection
This commit is contained in:
parent
4cd2cce360
commit
b6a0969c1c
|
|
@ -2,7 +2,7 @@
|
|||
using Microsoft.AspNet.Mvc;
|
||||
using MvcSample.Models;
|
||||
|
||||
namespace MvcSample
|
||||
namespace MvcSample.RandomNameSpace
|
||||
{
|
||||
public class Home2Controller
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using Microsoft.AspNet.Mvc;
|
||||
<<<<<<< HEAD
|
||||
using MvcSample.Models;
|
||||
=======
|
||||
>>>>>>> Support per process caching of controller discovery
|
||||
|
||||
namespace MvcSample
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.AspNet.Mvc.Startup;
|
||||
|
|
@ -24,8 +25,11 @@ namespace MvcSample
|
|||
// HACK appbase doesn't seem to work. When in VS we're pointing at bin\Debug\Net45, so move up 3 directories
|
||||
string appRoot = Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "..", "..", ".."));
|
||||
|
||||
var serviceProvider = MvcServices.Create(appRoot);
|
||||
var handler = new MvcHandler(serviceProvider);
|
||||
var mvcServices = new MvcServices(appRoot);
|
||||
|
||||
mvcServices.Finalize();
|
||||
|
||||
var handler = (MvcHandler)(ActivatorUtilities.CreateInstance(mvcServices.Services, typeof(MvcHandler)));
|
||||
|
||||
builder.Run(async context =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,20 +8,18 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
public class MvcHandler
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IActionInvokerFactory _actionInvokerFactory;
|
||||
|
||||
public MvcHandler(IServiceProvider serviceProvider)
|
||||
public MvcHandler(IActionInvokerFactory actionInvokerFactory)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_actionInvokerFactory = actionInvokerFactory;
|
||||
}
|
||||
|
||||
public Task ExecuteAsync(HttpContext context, IRouteData routeData)
|
||||
{
|
||||
var requestContext = new RequestContext(context, routeData);
|
||||
|
||||
IActionInvokerFactory invokerFactory = _serviceProvider.GetService<IActionInvokerFactory>();
|
||||
|
||||
var invoker = invokerFactory.CreateInvoker(requestContext);
|
||||
var invoker = _actionInvokerFactory.CreateInvoker(requestContext);
|
||||
|
||||
return invoker.InvokeActionAsync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,113 @@
|
|||
using Microsoft.AspNet.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
using Microsoft.AspNet.FileSystems;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Startup
|
||||
{
|
||||
public static class MvcServices
|
||||
public class MvcServices
|
||||
{
|
||||
public static ServiceProvider Create(string appRoot)
|
||||
private object _lock = new object();
|
||||
|
||||
private List<Type> _typesToFinalize = new List<Type>();
|
||||
|
||||
public ServiceProvider Services { get; private set; }
|
||||
|
||||
public MvcServices(string appRoot)
|
||||
{
|
||||
var services = new ServiceProvider();
|
||||
services.Add<IControllerFactory, DefaultControllerFactory>();
|
||||
services.Add<IActionInvokerFactory, ActionInvokerFactory>();
|
||||
services.Add<IActionResultHelper, ActionResultHelper>();
|
||||
services.Add<IActionResultFactory, ActionResultFactory>();
|
||||
services.Add<IActionDescriptorProvider, ActionDescriptorProvider>();
|
||||
services.Add<IActionInvokerProvider, ActionInvokerProvider>();
|
||||
Services = new ServiceProvider();
|
||||
|
||||
services.AddInstance<IFileSystem>(new PhysicalFileSystem(appRoot));
|
||||
services.AddInstance<IMvcRazorHost>(new MvcRazorHost("Microsoft.AspNet.Mvc.Razor.RazorView<dynamic>"));
|
||||
#if NET45
|
||||
services.Add<ICompilationService, CscBasedCompilationService>();
|
||||
#endif
|
||||
services.Add<IRazorCompilationService, RazorCompilationService>();
|
||||
services.Add<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
||||
services.Add<IViewEngine, RazorViewEngine>();
|
||||
AddAndRegisterForFinalization<ControllerCache, DefaultControllerCache>();
|
||||
AddAndRegisterForFinalization<IControllerFactory, DefaultControllerFactory>();
|
||||
AddAndRegisterForFinalization<IActionInvokerFactory, ActionInvokerFactory>();
|
||||
AddAndRegisterForFinalization<IActionResultHelper, ActionResultHelper>();
|
||||
AddAndRegisterForFinalization<IActionResultFactory, ActionResultFactory>();
|
||||
AddAndRegisterForFinalization<IActionDescriptorProvider, ActionDescriptorProvider>();
|
||||
AddAndRegisterForFinalization<IActionInvokerProvider, ActionInvokerProvider>();
|
||||
|
||||
return services;
|
||||
// need singleton support here.
|
||||
// AddAndRegisterForFinalization<SkipAssemblies, DefaultSkipAssemblies>();
|
||||
AddInstanceAndRegisterForFinalization<ControllerCache>(new DefaultControllerCache(new DefaultSkipAssemblies()));
|
||||
AddInstanceAndRegisterForFinalization<IFileSystem>(new PhysicalFileSystem(appRoot));
|
||||
AddInstanceAndRegisterForFinalization<IMvcRazorHost>(new MvcRazorHost("Microsoft.AspNet.Mvc.Razor.RazorView<dynamic>"));
|
||||
|
||||
#if NET45
|
||||
AddAndRegisterForFinalization<ICompilationService, CscBasedCompilationService>();
|
||||
#endif
|
||||
AddAndRegisterForFinalization<IRazorCompilationService, RazorCompilationService>();
|
||||
AddAndRegisterForFinalization<IVirtualPathViewFactory, VirtualPathViewFactory>();
|
||||
AddAndRegisterForFinalization<IViewEngine, RazorViewEngine>();
|
||||
}
|
||||
|
||||
public void AddAndRegisterForFinalization<T, U>() where U : T
|
||||
{
|
||||
Services.Add<T, U>();
|
||||
#if NET45
|
||||
if (typeof(IFinalizeSetup).IsAssignableFrom(typeof(U)))
|
||||
#else
|
||||
if (typeof(IFinalizeSetup).GetTypeInfo().IsAssignableFrom(typeof(U).GetTypeInfo()))
|
||||
#endif
|
||||
{
|
||||
_typesToFinalize.Add(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddInstanceAndRegisterForFinalization<T>(object instance)
|
||||
{
|
||||
Services.AddInstance<T>(instance);
|
||||
|
||||
if ((instance as IFinalizeSetup) != null)
|
||||
{
|
||||
_typesToFinalize.Add(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
public void Finalize()
|
||||
{
|
||||
if (_typesToFinalize == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We want to lock around here so finalization happens just once.
|
||||
// This is not a code intended to be used during request, so the lock is just a safety precaution.
|
||||
lock (_lock)
|
||||
{
|
||||
if (_typesToFinalize == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var markerType in _typesToFinalize)
|
||||
{
|
||||
var services = this.Services.GetService(markerType);
|
||||
|
||||
var serviceToFinalize = services as IFinalizeSetup;
|
||||
|
||||
if (serviceToFinalize != null)
|
||||
{
|
||||
serviceToFinalize.FinalizeSetup();
|
||||
}
|
||||
else
|
||||
{
|
||||
var setOfServices = services as IEnumerable;
|
||||
|
||||
if (setOfServices != null)
|
||||
{
|
||||
foreach (var service in setOfServices.OfType<IFinalizeSetup>())
|
||||
{
|
||||
service.FinalizeSetup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_typesToFinalize = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,20 @@
|
|||
using System;
|
||||
using Microsoft.AspNet.DependencyInjection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ActionInvokerProvider : IActionInvokerProvider
|
||||
{
|
||||
private IActionResultFactory _actionResultFactory;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IActionResultFactory _actionResultFactory;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IControllerFactory _controrllerFactory;
|
||||
|
||||
public ActionInvokerProvider(IActionResultFactory actionResultFactory,
|
||||
IControllerFactory controllerFactory,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_actionResultFactory = actionResultFactory;
|
||||
_controrllerFactory = controllerFactory;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
|
|
@ -24,6 +28,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
requestContext,
|
||||
controllerActionDescriptor,
|
||||
_actionResultFactory,
|
||||
_controrllerFactory,
|
||||
_serviceProvider);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,22 +14,24 @@ namespace Microsoft.AspNet.Mvc
|
|||
private readonly ControllerBasedActionDescriptor _descriptor;
|
||||
private readonly IActionResultFactory _actionResultFactory;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IControllerFactory _controllerFactory;
|
||||
|
||||
public ControllerActionInvoker(RequestContext requestContext,
|
||||
ControllerBasedActionDescriptor descriptor,
|
||||
IActionResultFactory actionResultFactory,
|
||||
IControllerFactory controllerFactory,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_requestContext = requestContext;
|
||||
_descriptor = descriptor;
|
||||
_actionResultFactory = actionResultFactory;
|
||||
_controllerFactory = controllerFactory;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
public Task InvokeActionAsync()
|
||||
{
|
||||
var factory = _serviceProvider.GetService<IControllerFactory>();
|
||||
object controller = factory.CreateController(_requestContext.HttpContext, _descriptor.ControllerName);
|
||||
object controller = _controllerFactory.CreateController(_requestContext.HttpContext, _descriptor.ControllerName);
|
||||
|
||||
if (controller == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public abstract class ControllerCache
|
||||
{
|
||||
public abstract IEnumerable<ControllerDescriptor> GetController(string controllerName);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ControllerDescriptor
|
||||
{
|
||||
public ControllerDescriptor(Type controllerType, Assembly assembly)
|
||||
{
|
||||
if (controllerType == null)
|
||||
{
|
||||
throw new ArgumentNullException("controllerType");
|
||||
}
|
||||
|
||||
if (assembly == null)
|
||||
{
|
||||
throw new ArgumentNullException("assembly");
|
||||
}
|
||||
|
||||
ControllerType = controllerType;
|
||||
Assembly = assembly;
|
||||
|
||||
ControllerName = controllerType.Name;
|
||||
AssemblyName = assembly.GetName().Name;
|
||||
}
|
||||
|
||||
public string ControllerName { get; private set; }
|
||||
|
||||
public string AssemblyName { get; private set; }
|
||||
|
||||
public Type ControllerType { get; private set; }
|
||||
|
||||
public Assembly Assembly { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultControllerCache : ControllerCache, IFinalizeSetup
|
||||
{
|
||||
private readonly SkipAssemblies _skipAssemblies;
|
||||
|
||||
public IReadOnlyDictionary<string, IEnumerable<ControllerDescriptor>> Controllers { get; protected set; }
|
||||
|
||||
public virtual void FinalizeSetup()
|
||||
{
|
||||
Controllers = ScanAppDomain();
|
||||
}
|
||||
|
||||
public DefaultControllerCache(SkipAssemblies skipAssemblies)
|
||||
{
|
||||
_skipAssemblies = skipAssemblies ?? new SkipNoAssemblies();
|
||||
}
|
||||
|
||||
public override IEnumerable<ControllerDescriptor> GetController(string controllerName)
|
||||
{
|
||||
if (Controllers == null)
|
||||
{
|
||||
throw new InvalidOperationException("Finalizing the setup must happen prior to accessing controllers");
|
||||
}
|
||||
|
||||
return Controllers[controllerName];
|
||||
}
|
||||
|
||||
public Dictionary<string, IEnumerable<ControllerDescriptor>> ScanAppDomain()
|
||||
{
|
||||
var dictionary = new Dictionary<string, IEnumerable<ControllerDescriptor>>(StringComparer.Ordinal);
|
||||
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Where(AllowAssembly))
|
||||
{
|
||||
foreach (var type in assembly.DefinedTypes.Where(IsController).Select(info => info.AsType()))
|
||||
{
|
||||
var descriptor = new ControllerDescriptor(type, assembly);
|
||||
|
||||
IEnumerable<ControllerDescriptor> controllerDescriptors;
|
||||
if (!dictionary.TryGetValue(type.Name, out controllerDescriptors))
|
||||
{
|
||||
controllerDescriptors = new List<ControllerDescriptor>();
|
||||
dictionary.Add(descriptor.ControllerName, controllerDescriptors);
|
||||
}
|
||||
|
||||
((List<ControllerDescriptor>)controllerDescriptors).Add(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public virtual bool IsController(TypeInfo typeInfo)
|
||||
{
|
||||
if (typeInfo == null)
|
||||
{
|
||||
throw new ArgumentNullException("typeInfo");
|
||||
}
|
||||
|
||||
bool validController = typeInfo.IsClass &&
|
||||
!typeInfo.IsAbstract &&
|
||||
!typeInfo.ContainsGenericParameters;
|
||||
|
||||
validController = validController && typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
return validController;
|
||||
}
|
||||
|
||||
private bool AllowAssembly(Assembly assembly)
|
||||
{
|
||||
return !_skipAssemblies.Skip(assembly, SkipAssemblies.ControllerDiscoveryScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Abstractions;
|
||||
|
|
@ -10,10 +9,12 @@ namespace Microsoft.AspNet.Mvc
|
|||
public class DefaultControllerFactory : IControllerFactory
|
||||
{
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ControllerCache _controllerCache;
|
||||
|
||||
public DefaultControllerFactory(IServiceProvider serviceProvider)
|
||||
public DefaultControllerFactory(IServiceProvider serviceProvider, ControllerCache cache)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
_controllerCache = cache;
|
||||
}
|
||||
|
||||
public object CreateController(HttpContext context, string controllerName)
|
||||
|
|
@ -23,29 +24,26 @@ namespace Microsoft.AspNet.Mvc
|
|||
controllerName += "Controller";
|
||||
}
|
||||
|
||||
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
try
|
||||
{
|
||||
var type = a.GetType(controllerName) ??
|
||||
a.GetType(a.GetName().Name + "." + controllerName);
|
||||
#if NET45
|
||||
type = type ?? a.GetTypes().FirstOrDefault(t => t.Name.Equals(controllerName, StringComparison.OrdinalIgnoreCase));
|
||||
#endif
|
||||
var controllers = _controllerCache.GetController(controllerName);
|
||||
|
||||
if (type != null)
|
||||
try
|
||||
{
|
||||
var type = controllers.SingleOrDefault().ControllerType;
|
||||
|
||||
if (type != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ActivatorUtilities.CreateInstance(_serviceProvider, type);
|
||||
}
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
}
|
||||
}
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
// TODO: Trace here
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// TODO: Trace here
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
throw new InvalidOperationException("Ambiguity: Duplicate controllers match the controller name");
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultSkipAssemblies : SkipAssemblies
|
||||
{
|
||||
private HashSet<string> _hash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public DefaultSkipAssemblies(IEnumerable<string> assemblyNames)
|
||||
{
|
||||
InitializeHash(assemblyNames);
|
||||
}
|
||||
|
||||
public DefaultSkipAssemblies()
|
||||
{
|
||||
#if NET45
|
||||
InitializeHash(@"
|
||||
klr.net45.managed
|
||||
Microsoft.Net.Runtime.Interfaces
|
||||
klr.host
|
||||
System
|
||||
System.Core
|
||||
System.Configuration
|
||||
System.Xml
|
||||
Microsoft.Net.ApplicationHost
|
||||
Microsoft.Net.Runtime
|
||||
Newtonsoft.Json
|
||||
System.Numerics
|
||||
System.ComponentModel.DataAnnotations
|
||||
System.Runtime.Serialization
|
||||
System.Xml.Linq
|
||||
System.Data
|
||||
Microsoft.CodeAnalysis
|
||||
System.Collections.Immutable
|
||||
System.Runtime
|
||||
Microsoft.CodeAnalysis.CSharp
|
||||
System.IO.Compression
|
||||
Microsoft.AspNet.FileSystems
|
||||
Microsoft.AspNet.Abstractions
|
||||
Microsoft.AspNet.DependencyInjection
|
||||
Microsoft.AspNet.Razor
|
||||
Newtonsoft.Json
|
||||
System.Linq
|
||||
System.Collections
|
||||
System.Runtime.Extensions
|
||||
System.Threading
|
||||
System.Reflection.Metadata.Ecma335
|
||||
Microsoft.AspNet.Mvc.ModelBinding
|
||||
Microsoft.AspNet.Mvc.Rendering
|
||||
Microsoft.AspNet.Mvc
|
||||
Microsoft.AspNet.Mvc.Razor.Host
|
||||
Microsoft.AspNet.Mvc.Razor
|
||||
Microsoft.AspNet.Mvc.Startup
|
||||
Owin
|
||||
Microsoft.Owin
|
||||
Microsoft.Owin.Diagnostics
|
||||
Microsoft.Owin.Hosting
|
||||
Microsoft.Owin.Host.HttpListener
|
||||
Microsoft.AspNet.AppBuilderSupport
|
||||
Anonymously Hosted DynamicMethods Assembly
|
||||
Microsoft.AspNet.PipelineCore
|
||||
Microsoft.AspNet.FeatureModel
|
||||
mscorlib
|
||||
klr.net45.managed
|
||||
Microsoft.Net.Runtime.Interfaces
|
||||
klr.host
|
||||
System
|
||||
System.Core
|
||||
System.Configuration
|
||||
System.Xml
|
||||
Microsoft.Net.ApplicationHost
|
||||
Microsoft.Net.Runtime
|
||||
Newtonsoft.Json
|
||||
System.Numerics
|
||||
System.ComponentModel.DataAnnotations
|
||||
System.Runtime.Serialization
|
||||
System.Xml.Linq
|
||||
System.Data
|
||||
Microsoft.CodeAnalysis
|
||||
System.Collections.Immutable
|
||||
System.Runtime
|
||||
Microsoft.CodeAnalysis.CSharp
|
||||
System.IO.Compression
|
||||
Microsoft.AspNet.FileSystems
|
||||
Microsoft.AspNet.Abstractions
|
||||
Microsoft.AspNet.DependencyInjection
|
||||
Microsoft.AspNet.Razor
|
||||
Newtonsoft.Json
|
||||
System.Linq
|
||||
System.Collections
|
||||
System.Runtime.Extensions
|
||||
System.Threading
|
||||
System.Reflection.Metadata.Ecma335
|
||||
Microsoft.AspNet.Mvc.ModelBinding
|
||||
Microsoft.AspNet.Mvc.Rendering
|
||||
Microsoft.AspNet.Mvc
|
||||
Microsoft.AspNet.Mvc.Razor.Host
|
||||
Microsoft.AspNet.Mvc.Razor
|
||||
Microsoft.AspNet.Mvc.Startup
|
||||
Owin
|
||||
Microsoft.Owin
|
||||
Microsoft.Owin.Diag".Split(new char[] { '\r', '\n'}, StringSplitOptions.RemoveEmptyEntries));
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeHash(IEnumerable<string> assemblyNames)
|
||||
{
|
||||
if (assemblyNames == null)
|
||||
{
|
||||
throw new ArgumentNullException("assemblyNames");
|
||||
}
|
||||
|
||||
foreach (var assemblyName in assemblyNames)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(assemblyName))
|
||||
{
|
||||
_hash.Add(assemblyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Skip(Assembly assembly, string scope)
|
||||
{
|
||||
if (scope == null ||
|
||||
!string.Equals(scope, SkipAssemblies.ControllerDiscoveryScope, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string name = assembly.GetName().Name;
|
||||
|
||||
bool contains = _hash.Contains(name);
|
||||
|
||||
return contains;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IFinalizeSetup
|
||||
{
|
||||
void FinalizeSetup();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public abstract class SkipAssemblies
|
||||
{
|
||||
public static readonly string ControllerDiscoveryScope = "DCS";
|
||||
|
||||
public abstract bool Skip(Assembly assembly, string scope);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class SkipNoAssemblies : SkipAssemblies
|
||||
{
|
||||
public override bool Skip(Assembly assembly, string scope)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue